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, 2005
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>
bb5e3b2f129cc39517b925419c22f69a378ec023eh#include <sys/mac_wifi.h>
bb5e3b2f129cc39517b925419c22f69a378ec023eh#include <sys/varargs.h>
bb5e3b2f129cc39517b925419c22f69a378ec023eh#include <sys/pci.h>
bb5e3b2f129cc39517b925419c22f69a378ec023eh#include <sys/policy.h>
bb5e3b2f129cc39517b925419c22f69a378ec023eh#include <sys/random.h>
924f3e72988efae04c4357a6686a06ba300bab18eh#include <sys/crypto/common.h>
924f3e72988efae04c4357a6686a06ba300bab18eh#include <sys/crypto/api.h>
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh#include "ipw2200.h"
bb5e3b2f129cc39517b925419c22f69a378ec023eh#include "ipw2200_impl.h"
bb5e3b2f129cc39517b925419c22f69a378ec023eh#include <inet/wifi_ioctl.h>
bb5e3b2f129cc39517b925419c22f69a378ec023eh
924f3e72988efae04c4357a6686a06ba300bab18eh/*
924f3e72988efae04c4357a6686a06ba300bab18eh * for net80211 kernel usage
924f3e72988efae04c4357a6686a06ba300bab18eh */
924f3e72988efae04c4357a6686a06ba300bab18eh#include <sys/net80211.h>
924f3e72988efae04c4357a6686a06ba300bab18eh#include <sys/net80211_proto.h>
924f3e72988efae04c4357a6686a06ba300bab18eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh/*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * minimal size reserved in tx-ring
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh#define IPW2200_TX_RING_MIN (8)
bb5e3b2f129cc39517b925419c22f69a378ec023eh#define IPW2200_TXBUF_SIZE (IEEE80211_MAX_LEN)
bb5e3b2f129cc39517b925419c22f69a378ec023eh#define IPW2200_RXBUF_SIZE (4096)
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic void *ipw2200_ssp = NULL;
193974072f41a843678abf5f61979c748687e66bSherry Moorestatic char ipw2200_ident[] = IPW2200_DRV_DESC;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh/*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * PIO access attributor for registers
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic ddi_device_acc_attr_t ipw2200_csr_accattr = {
bb5e3b2f129cc39517b925419c22f69a378ec023eh DDI_DEVICE_ATTR_V0,
bb5e3b2f129cc39517b925419c22f69a378ec023eh DDI_STRUCTURE_LE_ACC,
bb5e3b2f129cc39517b925419c22f69a378ec023eh DDI_STRICTORDER_ACC
bb5e3b2f129cc39517b925419c22f69a378ec023eh};
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh/*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * DMA access attributor for descriptors
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic ddi_device_acc_attr_t ipw2200_dma_accattr = {
bb5e3b2f129cc39517b925419c22f69a378ec023eh DDI_DEVICE_ATTR_V0,
bb5e3b2f129cc39517b925419c22f69a378ec023eh DDI_NEVERSWAP_ACC,
bb5e3b2f129cc39517b925419c22f69a378ec023eh DDI_STRICTORDER_ACC
bb5e3b2f129cc39517b925419c22f69a378ec023eh};
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh/*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * Describes the chip's DMA engine
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic ddi_dma_attr_t ipw2200_dma_attr = {
bb5e3b2f129cc39517b925419c22f69a378ec023eh DMA_ATTR_V0, /* version */
bb5e3b2f129cc39517b925419c22f69a378ec023eh 0x0000000000000000ULL, /* addr_lo */
bb5e3b2f129cc39517b925419c22f69a378ec023eh 0x00000000ffffffffULL, /* addr_hi */
bb5e3b2f129cc39517b925419c22f69a378ec023eh 0x00000000ffffffffULL, /* counter */
bb5e3b2f129cc39517b925419c22f69a378ec023eh 0x0000000000000004ULL, /* alignment */
bb5e3b2f129cc39517b925419c22f69a378ec023eh 0xfff, /* burst */
bb5e3b2f129cc39517b925419c22f69a378ec023eh 1, /* min xfer */
bb5e3b2f129cc39517b925419c22f69a378ec023eh 0x00000000ffffffffULL, /* max xfer */
bb5e3b2f129cc39517b925419c22f69a378ec023eh 0x00000000ffffffffULL, /* seg boud */
bb5e3b2f129cc39517b925419c22f69a378ec023eh 1, /* s/g list */
bb5e3b2f129cc39517b925419c22f69a378ec023eh 1, /* granularity */
bb5e3b2f129cc39517b925419c22f69a378ec023eh 0 /* flags */
bb5e3b2f129cc39517b925419c22f69a378ec023eh};
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic uint8_t ipw2200_broadcast_addr[] = {
bb5e3b2f129cc39517b925419c22f69a378ec023eh 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
bb5e3b2f129cc39517b925419c22f69a378ec023eh};
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic const struct ieee80211_rateset ipw2200_rateset_11a = { 8,
bb5e3b2f129cc39517b925419c22f69a378ec023eh {12, 18, 24, 36, 48, 72, 96, 108}
bb5e3b2f129cc39517b925419c22f69a378ec023eh};
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic const struct ieee80211_rateset ipw2200_rateset_11b = { 4,
bb5e3b2f129cc39517b925419c22f69a378ec023eh {2, 4, 11, 22}
bb5e3b2f129cc39517b925419c22f69a378ec023eh};
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic const struct ieee80211_rateset ipw2200_rateset_11g = { 12,
bb5e3b2f129cc39517b925419c22f69a378ec023eh {2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108}
bb5e3b2f129cc39517b925419c22f69a378ec023eh};
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh/*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * Used by multi function thread
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023ehextern pri_t minclsyspri;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh/*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * ipw2200 specific hardware operations
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic void ipw2200_hwconf_get(struct ipw2200_softc *sc);
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic int ipw2200_chip_reset(struct ipw2200_softc *sc);
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic void ipw2200_master_stop(struct ipw2200_softc *sc);
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic void ipw2200_stop(struct ipw2200_softc *sc);
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic int ipw2200_config(struct ipw2200_softc *sc);
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic int ipw2200_cmd(struct ipw2200_softc *sc,
bb5e3b2f129cc39517b925419c22f69a378ec023eh uint32_t type, void *buf, size_t len, int async);
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic void ipw2200_ring_hwsetup(struct ipw2200_softc *sc);
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic int ipw2200_ring_alloc(struct ipw2200_softc *sc);
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic void ipw2200_ring_free(struct ipw2200_softc *sc);
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic void ipw2200_ring_reset(struct ipw2200_softc *sc);
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic int ipw2200_ring_init(struct ipw2200_softc *sc);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh/*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * GLD specific operations
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic int ipw2200_m_stat(void *arg, uint_t stat, uint64_t *val);
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic int ipw2200_m_start(void *arg);
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic void ipw2200_m_stop(void *arg);
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic int ipw2200_m_unicst(void *arg, const uint8_t *macaddr);
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic int ipw2200_m_multicst(void *arg, boolean_t add, const uint8_t *m);
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic int ipw2200_m_promisc(void *arg, boolean_t on);
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic void ipw2200_m_ioctl(void *arg, queue_t *wq, mblk_t *mp);
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic mblk_t *ipw2200_m_tx(void *arg, mblk_t *mp);
7efa17f5f4c3cc113e1b0a1e86f43d4bf2ede8fafei feng - Sun Microsystems - Beijing Chinastatic int ipw2200_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 ipw2200_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 ipw2200_m_propinfo(void *arg, const char *pr_name,
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer mac_prop_id_t wldp_pr_num, mac_prop_info_handle_t mph);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh/*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * Interrupt and Data transferring operations
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic uint_t ipw2200_intr(caddr_t arg);
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic int ipw2200_send(struct ieee80211com *ic, mblk_t *mp, uint8_t type);
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic void ipw2200_rcv_frame(struct ipw2200_softc *sc,
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct ipw2200_frame *frame);
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic void ipw2200_rcv_notif(struct ipw2200_softc *sc,
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct ipw2200_notif *notif);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh/*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * WiFi specific operations
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic int ipw2200_newstate(struct ieee80211com *ic,
bb5e3b2f129cc39517b925419c22f69a378ec023eh enum ieee80211_state state, int arg);
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic void ipw2200_thread(struct ipw2200_softc *sc);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh/*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * IOCTL Handler
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic int ipw2200_ioctl(struct ipw2200_softc *sc, queue_t *q, mblk_t *m);
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic int ipw2200_getset(struct ipw2200_softc *sc,
bb5e3b2f129cc39517b925419c22f69a378ec023eh mblk_t *m, uint32_t cmd, boolean_t *need_net80211);
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic int iwi_wificfg_radio(struct ipw2200_softc *sc,
bb5e3b2f129cc39517b925419c22f69a378ec023eh uint32_t cmd, wldp_t *outfp);
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic int iwi_wificfg_desrates(wldp_t *outfp);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
924f3e72988efae04c4357a6686a06ba300bab18eh/*
924f3e72988efae04c4357a6686a06ba300bab18eh * net80211 functions
924f3e72988efae04c4357a6686a06ba300bab18eh */
924f3e72988efae04c4357a6686a06ba300bab18ehextern uint8_t ieee80211_crypto_getciphertype(ieee80211com_t *ic);
924f3e72988efae04c4357a6686a06ba300bab18ehextern void ieee80211_notify_node_join(ieee80211com_t *ic,
924f3e72988efae04c4357a6686a06ba300bab18eh ieee80211_node_t *in);
924f3e72988efae04c4357a6686a06ba300bab18ehextern void ieee80211_notify_node_leave(ieee80211com_t *ic,
924f3e72988efae04c4357a6686a06ba300bab18eh ieee80211_node_t *in);
924f3e72988efae04c4357a6686a06ba300bab18eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh/*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * Mac Call Back entries
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023ehmac_callbacks_t ipw2200_m_callbacks = {
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer MC_IOCTL | MC_SETPROP | MC_GETPROP | MC_PROPINFO,
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2200_m_stat,
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2200_m_start,
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2200_m_stop,
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2200_m_promisc,
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2200_m_multicst,
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2200_m_unicst,
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2200_m_tx,
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer NULL,
7efa17f5f4c3cc113e1b0a1e86f43d4bf2ede8fafei feng - Sun Microsystems - Beijing China ipw2200_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 ipw2200_m_setprop,
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer ipw2200_m_getprop,
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer ipw2200_m_propinfo
bb5e3b2f129cc39517b925419c22f69a378ec023eh};
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh/*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * DEBUG Facility
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh#define MAX_MSG (128)
bb5e3b2f129cc39517b925419c22f69a378ec023ehuint32_t ipw2200_debug = 0;
bb5e3b2f129cc39517b925419c22f69a378ec023eh/*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * supported debug marks are:
bb5e3b2f129cc39517b925419c22f69a378ec023eh * | IPW2200_DBG_CSR
bb5e3b2f129cc39517b925419c22f69a378ec023eh * | IPW2200_DBG_TABLE
bb5e3b2f129cc39517b925419c22f69a378ec023eh * | IPW2200_DBG_HWCAP
bb5e3b2f129cc39517b925419c22f69a378ec023eh * | IPW2200_DBG_TX
bb5e3b2f129cc39517b925419c22f69a378ec023eh * | IPW2200_DBG_INIT
bb5e3b2f129cc39517b925419c22f69a378ec023eh * | IPW2200_DBG_FW
bb5e3b2f129cc39517b925419c22f69a378ec023eh * | IPW2200_DBG_NOTIF
bb5e3b2f129cc39517b925419c22f69a378ec023eh * | IPW2200_DBG_SCAN
bb5e3b2f129cc39517b925419c22f69a378ec023eh * | IPW2200_DBG_IOCTL
bb5e3b2f129cc39517b925419c22f69a378ec023eh * | IPW2200_DBG_RING
bb5e3b2f129cc39517b925419c22f69a378ec023eh * | IPW2200_DBG_INT
bb5e3b2f129cc39517b925419c22f69a378ec023eh * | IPW2200_DBG_RX
bb5e3b2f129cc39517b925419c22f69a378ec023eh * | IPW2200_DBG_DMA
bb5e3b2f129cc39517b925419c22f69a378ec023eh * | IPW2200_DBG_GLD
bb5e3b2f129cc39517b925419c22f69a378ec023eh * | IPW2200_DBG_WIFI
bb5e3b2f129cc39517b925419c22f69a378ec023eh * | IPW2200_DBG_SOFTINT
922d2c76afbee21520ffa2088c4e60dcb80d3945eh * | IPW2200_DBG_SUSPEND
7efa17f5f4c3cc113e1b0a1e86f43d4bf2ede8fafei feng - Sun Microsystems - Beijing China * | IPW2200_DBG_BRUSSELS
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh/*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * Global tunning parameter 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
bb5e3b2f129cc39517b925419c22f69a378ec023eh#define IEEE80211_IS_CHAN_2GHZ(_c) \
bb5e3b2f129cc39517b925419c22f69a378ec023eh (((_c)->ich_flags & IEEE80211_CHAN_2GHZ) != 0)
bb5e3b2f129cc39517b925419c22f69a378ec023eh#define IEEE80211_IS_CHAN_5GHZ(_c) \
bb5e3b2f129cc39517b925419c22f69a378ec023eh (((_c)->ich_flags & IEEE80211_CHAN_5GHZ) != 0)
bb5e3b2f129cc39517b925419c22f69a378ec023eh#define isset(a, i) ((a)[(i)/NBBY] & (1 << ((i)%NBBY)))
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023ehvoid
bb5e3b2f129cc39517b925419c22f69a378ec023ehipw2200_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", IPW2200_DRV_NAME, instance, buf);
bb5e3b2f129cc39517b925419c22f69a378ec023eh } else
bb5e3b2f129cc39517b925419c22f69a378ec023eh cmn_err(level, "%s: %s", IPW2200_DRV_NAME, buf);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh}
bb5e3b2f129cc39517b925419c22f69a378ec023eh
922d2c76afbee21520ffa2088c4e60dcb80d3945eh/*
922d2c76afbee21520ffa2088c4e60dcb80d3945eh * Set up pci
922d2c76afbee21520ffa2088c4e60dcb80d3945eh */
922d2c76afbee21520ffa2088c4e60dcb80d3945ehint
922d2c76afbee21520ffa2088c4e60dcb80d3945ehipw2200_setup_pci(dev_info_t *dip, struct ipw2200_softc *sc)
922d2c76afbee21520ffa2088c4e60dcb80d3945eh{
922d2c76afbee21520ffa2088c4e60dcb80d3945eh ddi_acc_handle_t cfgh;
922d2c76afbee21520ffa2088c4e60dcb80d3945eh caddr_t regs;
922d2c76afbee21520ffa2088c4e60dcb80d3945eh int err;
922d2c76afbee21520ffa2088c4e60dcb80d3945eh
922d2c76afbee21520ffa2088c4e60dcb80d3945eh /*
922d2c76afbee21520ffa2088c4e60dcb80d3945eh * Map config spaces register to read the vendor id, device id, sub
922d2c76afbee21520ffa2088c4e60dcb80d3945eh * vendor id, and sub device id.
922d2c76afbee21520ffa2088c4e60dcb80d3945eh */
922d2c76afbee21520ffa2088c4e60dcb80d3945eh err = ddi_regs_map_setup(dip, IPW2200_PCI_CFG_RNUM, &regs,
922d2c76afbee21520ffa2088c4e60dcb80d3945eh 0, 0, &ipw2200_csr_accattr, &cfgh);
922d2c76afbee21520ffa2088c4e60dcb80d3945eh if (err != DDI_SUCCESS) {
922d2c76afbee21520ffa2088c4e60dcb80d3945eh IPW2200_WARN((dip, CE_WARN,
922d2c76afbee21520ffa2088c4e60dcb80d3945eh "ipw2200_attach(): unable to map spaces regs\n"));
922d2c76afbee21520ffa2088c4e60dcb80d3945eh return (DDI_FAILURE);
922d2c76afbee21520ffa2088c4e60dcb80d3945eh }
922d2c76afbee21520ffa2088c4e60dcb80d3945eh
922d2c76afbee21520ffa2088c4e60dcb80d3945eh ddi_put8(cfgh, (uint8_t *)(regs + 0x41), 0);
922d2c76afbee21520ffa2088c4e60dcb80d3945eh sc->sc_vendor = ddi_get16(cfgh,
922d2c76afbee21520ffa2088c4e60dcb80d3945eh (uint16_t *)((uintptr_t)regs + PCI_CONF_VENID));
922d2c76afbee21520ffa2088c4e60dcb80d3945eh sc->sc_device = ddi_get16(cfgh,
922d2c76afbee21520ffa2088c4e60dcb80d3945eh (uint16_t *)((uintptr_t)regs + PCI_CONF_DEVID));
922d2c76afbee21520ffa2088c4e60dcb80d3945eh sc->sc_subven = ddi_get16(cfgh,
922d2c76afbee21520ffa2088c4e60dcb80d3945eh (uint16_t *)((uintptr_t)regs + PCI_CONF_SUBVENID));
922d2c76afbee21520ffa2088c4e60dcb80d3945eh sc->sc_subdev = ddi_get16(cfgh,
922d2c76afbee21520ffa2088c4e60dcb80d3945eh (uint16_t *)((uintptr_t)regs + PCI_CONF_SUBSYSID));
922d2c76afbee21520ffa2088c4e60dcb80d3945eh IPW2200_DBG(IPW2200_DBG_WIFI, (sc->sc_dip, CE_CONT,
922d2c76afbee21520ffa2088c4e60dcb80d3945eh "ipw2200_setup_pci(): vendor = 0x%04x, devic = 0x%04x,"
922d2c76afbee21520ffa2088c4e60dcb80d3945eh "subversion = 0x%04x, subdev = 0x%04x",
922d2c76afbee21520ffa2088c4e60dcb80d3945eh sc->sc_vendor, sc->sc_device, sc->sc_subven, sc->sc_subdev));
922d2c76afbee21520ffa2088c4e60dcb80d3945eh
922d2c76afbee21520ffa2088c4e60dcb80d3945eh ddi_regs_map_free(&cfgh);
922d2c76afbee21520ffa2088c4e60dcb80d3945eh
922d2c76afbee21520ffa2088c4e60dcb80d3945eh return (DDI_SUCCESS);
922d2c76afbee21520ffa2088c4e60dcb80d3945eh
922d2c76afbee21520ffa2088c4e60dcb80d3945eh}
922d2c76afbee21520ffa2088c4e60dcb80d3945eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh/*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * Device operations
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023ehint
bb5e3b2f129cc39517b925419c22f69a378ec023ehipw2200_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
bb5e3b2f129cc39517b925419c22f69a378ec023eh{
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct ipw2200_softc *sc;
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
922d2c76afbee21520ffa2088c4e60dcb80d3945eh switch (cmd) {
922d2c76afbee21520ffa2088c4e60dcb80d3945eh case DDI_ATTACH:
922d2c76afbee21520ffa2088c4e60dcb80d3945eh break;
922d2c76afbee21520ffa2088c4e60dcb80d3945eh case DDI_RESUME:
922d2c76afbee21520ffa2088c4e60dcb80d3945eh sc = ddi_get_soft_state(ipw2200_ssp, ddi_get_instance(dip));
922d2c76afbee21520ffa2088c4e60dcb80d3945eh ASSERT(sc != NULL);
922d2c76afbee21520ffa2088c4e60dcb80d3945eh
922d2c76afbee21520ffa2088c4e60dcb80d3945eh /*
922d2c76afbee21520ffa2088c4e60dcb80d3945eh * set up pci
922d2c76afbee21520ffa2088c4e60dcb80d3945eh */
922d2c76afbee21520ffa2088c4e60dcb80d3945eh err = ipw2200_setup_pci(dip, sc);
922d2c76afbee21520ffa2088c4e60dcb80d3945eh if (err != DDI_SUCCESS) {
922d2c76afbee21520ffa2088c4e60dcb80d3945eh IPW2200_DBG(IPW2200_DBG_SUSPEND, (sc->sc_dip, CE_CONT,
922d2c76afbee21520ffa2088c4e60dcb80d3945eh "ipw2200_attach(): resume failure\n"));
922d2c76afbee21520ffa2088c4e60dcb80d3945eh return (DDI_FAILURE);
922d2c76afbee21520ffa2088c4e60dcb80d3945eh }
922d2c76afbee21520ffa2088c4e60dcb80d3945eh
922d2c76afbee21520ffa2088c4e60dcb80d3945eh /*
922d2c76afbee21520ffa2088c4e60dcb80d3945eh * resume hardware.
922d2c76afbee21520ffa2088c4e60dcb80d3945eh * If it was on runnning status, reset to INIT state
922d2c76afbee21520ffa2088c4e60dcb80d3945eh */
922d2c76afbee21520ffa2088c4e60dcb80d3945eh sc->sc_flags &= ~IPW2200_FLAG_SUSPEND;
922d2c76afbee21520ffa2088c4e60dcb80d3945eh if (sc->sc_flags & IPW2200_FLAG_RUNNING)
922d2c76afbee21520ffa2088c4e60dcb80d3945eh (void) ipw2200_init(sc);
922d2c76afbee21520ffa2088c4e60dcb80d3945eh
922d2c76afbee21520ffa2088c4e60dcb80d3945eh IPW2200_DBG(IPW2200_DBG_SUSPEND, (sc->sc_dip, CE_CONT,
922d2c76afbee21520ffa2088c4e60dcb80d3945eh "ipw2200_attach(): resume successful\n"));
922d2c76afbee21520ffa2088c4e60dcb80d3945eh return (DDI_SUCCESS);
922d2c76afbee21520ffa2088c4e60dcb80d3945eh default:
922d2c76afbee21520ffa2088c4e60dcb80d3945eh return (DDI_FAILURE);
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh instance = ddi_get_instance(dip);
bb5e3b2f129cc39517b925419c22f69a378ec023eh err = ddi_soft_state_zalloc(ipw2200_ssp, instance);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (err != DDI_SUCCESS) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_WARN((dip, CE_WARN,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2200_attach(): unable to allocate soft state\n"));
bb5e3b2f129cc39517b925419c22f69a378ec023eh goto fail1;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc = ddi_get_soft_state(ipw2200_ssp, instance);
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_dip = dip;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
922d2c76afbee21520ffa2088c4e60dcb80d3945eh /* set up pci, put reg+0x41 0 */
922d2c76afbee21520ffa2088c4e60dcb80d3945eh err = ipw2200_setup_pci(dip, sc);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (err != DDI_SUCCESS) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_WARN((dip, CE_WARN,
922d2c76afbee21520ffa2088c4e60dcb80d3945eh "ipw2200_attach(): unable to setup pci\n"));
bb5e3b2f129cc39517b925419c22f69a378ec023eh goto fail2;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * Map operating registers
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh err = ddi_regs_map_setup(dip, IPW2200_PCI_CSR_RNUM, &sc->sc_regs,
bb5e3b2f129cc39517b925419c22f69a378ec023eh 0, 0, &ipw2200_csr_accattr, &sc->sc_ioh);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (err != DDI_SUCCESS) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_WARN((dip, CE_WARN,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2200_attach(): ddi_regs_map_setup() failed\n"));
bb5e3b2f129cc39517b925419c22f69a378ec023eh goto fail2;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * Reset the chip
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh err = ipw2200_chip_reset(sc);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (err != DDI_SUCCESS) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_WARN((dip, CE_WARN,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2200_attach(): ipw2200_chip_reset() failed\n"));
bb5e3b2f129cc39517b925419c22f69a378ec023eh goto fail3;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * Get the hardware configuration, including the MAC address
bb5e3b2f129cc39517b925419c22f69a378ec023eh * Then, init all the rings needed.
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2200_hwconf_get(sc);
bb5e3b2f129cc39517b925419c22f69a378ec023eh err = ipw2200_ring_init(sc);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (err != DDI_SUCCESS) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_WARN((dip, CE_WARN,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2200_attach(): ipw2200_ring_init() failed\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 IPW2200_WARN((dip, CE_WARN,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2200_attach(): ddi_get_iblock_cookie() failed\n"));
bb5e3b2f129cc39517b925419c22f69a378ec023eh goto fail4;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * interrupt lock
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh mutex_init(&sc->sc_ilock, "intr-lock", MUTEX_DRIVER,
bb5e3b2f129cc39517b925419c22f69a378ec023eh (void *) sc->sc_iblk);
bb5e3b2f129cc39517b925419c22f69a378ec023eh cv_init(&sc->sc_fw_cond, "firmware-ok", CV_DRIVER, NULL);
bb5e3b2f129cc39517b925419c22f69a378ec023eh cv_init(&sc->sc_cmd_status_cond, "cmd-status-ring", CV_DRIVER, NULL);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * command ring lock
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh mutex_init(&sc->sc_cmd_lock, "cmd-ring", MUTEX_DRIVER,
bb5e3b2f129cc39517b925419c22f69a378ec023eh (void *) sc->sc_iblk);
bb5e3b2f129cc39517b925419c22f69a378ec023eh cv_init(&sc->sc_cmd_cond, "cmd-ring", CV_DRIVER, NULL);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * tx ring lock
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh mutex_init(&sc->sc_tx_lock, "tx-ring", MUTEX_DRIVER,
bb5e3b2f129cc39517b925419c22f69a378ec023eh (void *) sc->sc_iblk);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
924f3e72988efae04c4357a6686a06ba300bab18eh /*
924f3e72988efae04c4357a6686a06ba300bab18eh * rescheduled lock
924f3e72988efae04c4357a6686a06ba300bab18eh */
924f3e72988efae04c4357a6686a06ba300bab18eh mutex_init(&sc->sc_resched_lock, "reschedule-lock", MUTEX_DRIVER,
924f3e72988efae04c4357a6686a06ba300bab18eh (void *) sc->sc_iblk);
924f3e72988efae04c4357a6686a06ba300bab18eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * multi-function lock, may acquire this during interrupt
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 /*
924f3e72988efae04c4357a6686a06ba300bab18eh * Initialize the WiFi part
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh ic = &sc->sc_ic;
bb5e3b2f129cc39517b925419c22f69a378ec023eh ic->ic_phytype = IEEE80211_T_OFDM;
bb5e3b2f129cc39517b925419c22f69a378ec023eh ic->ic_opmode = IEEE80211_M_STA;
bb5e3b2f129cc39517b925419c22f69a378ec023eh ic->ic_state = IEEE80211_S_INIT;
bb5e3b2f129cc39517b925419c22f69a378ec023eh ic->ic_maxrssi = 100; /* experimental number */
924f3e72988efae04c4357a6686a06ba300bab18eh ic->ic_caps =
924f3e72988efae04c4357a6686a06ba300bab18eh IEEE80211_C_SHPREAMBLE |
924f3e72988efae04c4357a6686a06ba300bab18eh IEEE80211_C_TXPMGT |
924f3e72988efae04c4357a6686a06ba300bab18eh IEEE80211_C_PMGT |
924f3e72988efae04c4357a6686a06ba300bab18eh IEEE80211_C_WPA;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * set mac addr
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh IEEE80211_ADDR_COPY(ic->ic_macaddr, sc->sc_macaddr);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * set supported .11a rates and channel - (2915ABG only)
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
922d2c76afbee21520ffa2088c4e60dcb80d3945eh if (sc->sc_device >= 0x4223) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh /* .11a rates */
bb5e3b2f129cc39517b925419c22f69a378ec023eh ic->ic_sup_rates[IEEE80211_MODE_11A] = ipw2200_rateset_11a;
bb5e3b2f129cc39517b925419c22f69a378ec023eh /* .11a channels */
bb5e3b2f129cc39517b925419c22f69a378ec023eh for (i = 36; i <= 64; i += 4) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh ic->ic_sup_channels[i].ich_freq =
bb5e3b2f129cc39517b925419c22f69a378ec023eh ieee80211_ieee2mhz(i, IEEE80211_CHAN_5GHZ);
bb5e3b2f129cc39517b925419c22f69a378ec023eh ic->ic_sup_channels[i].ich_flags = /* CHAN_A */
bb5e3b2f129cc39517b925419c22f69a378ec023eh IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_OFDM;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh for (i = 149; i <= 165; i += 4) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh ic->ic_sup_channels[i].ich_freq =
bb5e3b2f129cc39517b925419c22f69a378ec023eh ieee80211_ieee2mhz(i, IEEE80211_CHAN_5GHZ);
bb5e3b2f129cc39517b925419c22f69a378ec023eh ic->ic_sup_channels[i].ich_flags = /* CHAN_A */
bb5e3b2f129cc39517b925419c22f69a378ec023eh IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_OFDM;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * set supported .11b and .11g rates
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh ic->ic_sup_rates[IEEE80211_MODE_11B] = ipw2200_rateset_11b;
bb5e3b2f129cc39517b925419c22f69a378ec023eh ic->ic_sup_rates[IEEE80211_MODE_11G] = ipw2200_rateset_11g;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * set supported .11b and .11g channels(1 through 14)
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh for (i = 1; i < 14; i++) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh ic->ic_sup_channels[i].ich_freq =
bb5e3b2f129cc39517b925419c22f69a378ec023eh ieee80211_ieee2mhz(i, IEEE80211_CHAN_2GHZ);
bb5e3b2f129cc39517b925419c22f69a378ec023eh ic->ic_sup_channels[i].ich_flags =
bb5e3b2f129cc39517b925419c22f69a378ec023eh IEEE80211_CHAN_CCK | IEEE80211_CHAN_OFDM |
bb5e3b2f129cc39517b925419c22f69a378ec023eh IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * IBSS channal undefined for now
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh ic->ic_ibss_chan = &ic->ic_sup_channels[0];
bb5e3b2f129cc39517b925419c22f69a378ec023eh ic->ic_xmit = ipw2200_send;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * init generic layer, then override state transition machine
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh ieee80211_attach(ic);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
924f3e72988efae04c4357a6686a06ba300bab18eh /*
924f3e72988efae04c4357a6686a06ba300bab18eh * different instance has different WPA door
924f3e72988efae04c4357a6686a06ba300bab18eh */
924f3e72988efae04c4357a6686a06ba300bab18eh ieee80211_register_door(ic, ddi_driver_name(dip), instance);
924f3e72988efae04c4357a6686a06ba300bab18eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * Override 80211 default routines
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh ieee80211_media_init(ic); /* initial the node table and bss */
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_newstate = ic->ic_newstate;
bb5e3b2f129cc39517b925419c22f69a378ec023eh ic->ic_newstate = ipw2200_newstate;
bb5e3b2f129cc39517b925419c22f69a378ec023eh ic->ic_def_txkey = 0;
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 ipw2200_intr, (caddr_t)sc);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (err != DDI_SUCCESS) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_WARN((dip, CE_WARN,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2200_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;
924f3e72988efae04c4357a6686a06ba300bab18eh IEEE80211_ADDR_COPY(wd.wd_bssid, ic->ic_bss->in_bssid);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh macp = mac_alloc(MAC_VERSION);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (err != 0) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_WARN((dip, CE_WARN,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2200_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 = &ipw2200_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 IPW2200_WARN((dip, CE_WARN,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2200_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 IPW2200_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 IPW2200_WARN((dip, CE_WARN,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2200_attach(): ddi_create_minor_node() failed\n"));
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * Cache firmware will always be true
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh (void) ipw2200_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 ipw2200_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_cmd_lock);
bb5e3b2f129cc39517b925419c22f69a378ec023eh mutex_destroy(&sc->sc_tx_lock);
bb5e3b2f129cc39517b925419c22f69a378ec023eh mutex_destroy(&sc->sc_mflock);
924f3e72988efae04c4357a6686a06ba300bab18eh mutex_destroy(&sc->sc_resched_lock);
bb5e3b2f129cc39517b925419c22f69a378ec023eh cv_destroy(&sc->sc_fw_cond);
bb5e3b2f129cc39517b925419c22f69a378ec023eh cv_destroy(&sc->sc_cmd_status_cond);
bb5e3b2f129cc39517b925419c22f69a378ec023eh cv_destroy(&sc->sc_cmd_cond);
bb5e3b2f129cc39517b925419c22f69a378ec023eh cv_destroy(&sc->sc_mfthread_cv);
bb5e3b2f129cc39517b925419c22f69a378ec023ehfail4:
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2200_ring_free(sc);
bb5e3b2f129cc39517b925419c22f69a378ec023ehfail3:
bb5e3b2f129cc39517b925419c22f69a378ec023eh ddi_regs_map_free(&sc->sc_ioh);
bb5e3b2f129cc39517b925419c22f69a378ec023ehfail2:
bb5e3b2f129cc39517b925419c22f69a378ec023eh ddi_soft_state_free(ipw2200_ssp, instance);
bb5e3b2f129cc39517b925419c22f69a378ec023ehfail1:
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (err);
bb5e3b2f129cc39517b925419c22f69a378ec023eh}
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023ehint
bb5e3b2f129cc39517b925419c22f69a378ec023ehipw2200_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
bb5e3b2f129cc39517b925419c22f69a378ec023eh{
922d2c76afbee21520ffa2088c4e60dcb80d3945eh struct ipw2200_softc *sc;
bb5e3b2f129cc39517b925419c22f69a378ec023eh int err;
922d2c76afbee21520ffa2088c4e60dcb80d3945eh
922d2c76afbee21520ffa2088c4e60dcb80d3945eh sc = ddi_get_soft_state(ipw2200_ssp, ddi_get_instance(dip));
bb5e3b2f129cc39517b925419c22f69a378ec023eh ASSERT(sc != NULL);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
922d2c76afbee21520ffa2088c4e60dcb80d3945eh switch (cmd) {
922d2c76afbee21520ffa2088c4e60dcb80d3945eh case DDI_DETACH:
922d2c76afbee21520ffa2088c4e60dcb80d3945eh break;
922d2c76afbee21520ffa2088c4e60dcb80d3945eh case DDI_SUSPEND:
922d2c76afbee21520ffa2088c4e60dcb80d3945eh if (sc->sc_flags & IPW2200_FLAG_RUNNING) {
922d2c76afbee21520ffa2088c4e60dcb80d3945eh ipw2200_stop(sc);
922d2c76afbee21520ffa2088c4e60dcb80d3945eh }
922d2c76afbee21520ffa2088c4e60dcb80d3945eh sc->sc_flags |= IPW2200_FLAG_SUSPEND;
922d2c76afbee21520ffa2088c4e60dcb80d3945eh
922d2c76afbee21520ffa2088c4e60dcb80d3945eh IPW2200_DBG(IPW2200_DBG_SUSPEND, (sc->sc_dip, CE_CONT,
922d2c76afbee21520ffa2088c4e60dcb80d3945eh "ipw2200_detach(): suspend\n"));
922d2c76afbee21520ffa2088c4e60dcb80d3945eh return (DDI_SUCCESS);
922d2c76afbee21520ffa2088c4e60dcb80d3945eh default:
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (DDI_FAILURE);
922d2c76afbee21520ffa2088c4e60dcb80d3945eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh
42516a0c6ebf6e259c2abcd1ca315fec43268f39xinghua wen - Sun Microsystems - Beijing China err = mac_disable(sc->sc_ic.ic_mach);
42516a0c6ebf6e259c2abcd1ca315fec43268f39xinghua wen - Sun Microsystems - Beijing China if (err != DDI_SUCCESS)
42516a0c6ebf6e259c2abcd1ca315fec43268f39xinghua wen - Sun Microsystems - Beijing China return (err);
42516a0c6ebf6e259c2abcd1ca315fec43268f39xinghua wen - Sun Microsystems - Beijing China
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2200_stop(sc);
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 /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * Unregister from the MAC layer subsystem
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
42516a0c6ebf6e259c2abcd1ca315fec43268f39xinghua wen - Sun Microsystems - Beijing China (void) mac_unregister(sc->sc_ic.ic_mach);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh ddi_remove_intr(dip, IPW2200_PCI_INTR_NUM, sc->sc_iblk);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh mutex_destroy(&sc->sc_ilock);
bb5e3b2f129cc39517b925419c22f69a378ec023eh mutex_destroy(&sc->sc_cmd_lock);
bb5e3b2f129cc39517b925419c22f69a378ec023eh mutex_destroy(&sc->sc_tx_lock);
bb5e3b2f129cc39517b925419c22f69a378ec023eh mutex_destroy(&sc->sc_mflock);
924f3e72988efae04c4357a6686a06ba300bab18eh mutex_destroy(&sc->sc_resched_lock);
bb5e3b2f129cc39517b925419c22f69a378ec023eh cv_destroy(&sc->sc_fw_cond);
bb5e3b2f129cc39517b925419c22f69a378ec023eh cv_destroy(&sc->sc_cmd_status_cond);
bb5e3b2f129cc39517b925419c22f69a378ec023eh cv_destroy(&sc->sc_cmd_cond);
bb5e3b2f129cc39517b925419c22f69a378ec023eh cv_destroy(&sc->sc_mfthread_cv);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * Detach ieee80211
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh ieee80211_detach(&sc->sc_ic);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh (void) ipw2200_free_firmware(sc);
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2200_ring_free(sc);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh ddi_regs_map_free(&sc->sc_ioh);
bb5e3b2f129cc39517b925419c22f69a378ec023eh ddi_remove_minor_node(dip, NULL);
bb5e3b2f129cc39517b925419c22f69a378ec023eh ddi_soft_state_free(ipw2200_ssp, ddi_get_instance(dip));
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (DDI_SUCCESS);
bb5e3b2f129cc39517b925419c22f69a378ec023eh}
bb5e3b2f129cc39517b925419c22f69a378ec023eh
14d912249090fc833b92625af4f618803de6a6c6fei feng - Sun Microsystems - Beijing China/*
14d912249090fc833b92625af4f618803de6a6c6fei feng - Sun Microsystems - Beijing China * quiesce(9E) entry point.
14d912249090fc833b92625af4f618803de6a6c6fei feng - Sun Microsystems - Beijing China * This function is called when the system is single-threaded at high
14d912249090fc833b92625af4f618803de6a6c6fei feng - Sun Microsystems - Beijing China * PIL with preemption disabled. Therefore, this function must not be
14d912249090fc833b92625af4f618803de6a6c6fei feng - Sun Microsystems - Beijing China * blocked.
14d912249090fc833b92625af4f618803de6a6c6fei feng - Sun Microsystems - Beijing China * This function returns DDI_SUCCESS on success, or DDI_FAILURE on failure.
14d912249090fc833b92625af4f618803de6a6c6fei feng - Sun Microsystems - Beijing China * DDI_FAILURE indicates an error condition and should almost never happen.
14d912249090fc833b92625af4f618803de6a6c6fei feng - Sun Microsystems - Beijing China */
14d912249090fc833b92625af4f618803de6a6c6fei feng - Sun Microsystems - Beijing Chinastatic int
14d912249090fc833b92625af4f618803de6a6c6fei feng - Sun Microsystems - Beijing Chinaipw2200_quiesce(dev_info_t *dip)
76939ce0e89c177cb48bf98208fd3d831eb283d5eh{
76939ce0e89c177cb48bf98208fd3d831eb283d5eh struct ipw2200_softc *sc =
76939ce0e89c177cb48bf98208fd3d831eb283d5eh ddi_get_soft_state(ipw2200_ssp, ddi_get_instance(dip));
14d912249090fc833b92625af4f618803de6a6c6fei feng - Sun Microsystems - Beijing China if (sc == NULL)
14d912249090fc833b92625af4f618803de6a6c6fei feng - Sun Microsystems - Beijing China return (DDI_FAILURE);
14d912249090fc833b92625af4f618803de6a6c6fei feng - Sun Microsystems - Beijing China
faceed938d6ba7344a332694084d213905e93375fei feng - Sun Microsystems - Beijing China /* by pass any messages, if it's quiesce */
faceed938d6ba7344a332694084d213905e93375fei feng - Sun Microsystems - Beijing China ipw2200_debug = 0;
faceed938d6ba7344a332694084d213905e93375fei feng - Sun Microsystems - Beijing China
14d912249090fc833b92625af4f618803de6a6c6fei feng - Sun Microsystems - Beijing China /*
14d912249090fc833b92625af4f618803de6a6c6fei feng - Sun Microsystems - Beijing China * No more blocking is allowed while we are in the
14d912249090fc833b92625af4f618803de6a6c6fei feng - Sun Microsystems - Beijing China * quiesce(9E) entry point.
14d912249090fc833b92625af4f618803de6a6c6fei feng - Sun Microsystems - Beijing China */
14d912249090fc833b92625af4f618803de6a6c6fei feng - Sun Microsystems - Beijing China sc->sc_flags |= IPW2200_FLAG_QUIESCED;
76939ce0e89c177cb48bf98208fd3d831eb283d5eh
14d912249090fc833b92625af4f618803de6a6c6fei feng - Sun Microsystems - Beijing China /*
14d912249090fc833b92625af4f618803de6a6c6fei feng - Sun Microsystems - Beijing China * Disable and mask all interrupts.
14d912249090fc833b92625af4f618803de6a6c6fei feng - Sun Microsystems - Beijing China */
faceed938d6ba7344a332694084d213905e93375fei feng - Sun Microsystems - Beijing China ipw2200_master_stop(sc);
faceed938d6ba7344a332694084d213905e93375fei feng - Sun Microsystems - Beijing China ipw2200_csr_put32(sc, IPW2200_CSR_RST, IPW2200_RST_SW_RESET);
76939ce0e89c177cb48bf98208fd3d831eb283d5eh return (DDI_SUCCESS);
76939ce0e89c177cb48bf98208fd3d831eb283d5eh}
76939ce0e89c177cb48bf98208fd3d831eb283d5eh
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic void
bb5e3b2f129cc39517b925419c22f69a378ec023ehipw2200_stop(struct ipw2200_softc *sc)
bb5e3b2f129cc39517b925419c22f69a378ec023eh{
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct ieee80211com *ic = &sc->sc_ic;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_DBG(IPW2200_DBG_HWCAP, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2200_stop(): enter\n"));
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2200_master_stop(sc);
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2200_csr_put32(sc, IPW2200_CSR_RST, IPW2200_RST_SW_RESET);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * Reset ring
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2200_ring_reset(sc);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
faceed938d6ba7344a332694084d213905e93375fei feng - Sun Microsystems - Beijing China ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_flags &= ~IPW2200_FLAG_SCANNING;
924f3e72988efae04c4357a6686a06ba300bab18eh sc->sc_flags &= ~IPW2200_FLAG_ASSOCIATED;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
faceed938d6ba7344a332694084d213905e93375fei feng - Sun Microsystems - Beijing China IPW2200_DBG(IPW2200_DBG_HWCAP, (sc->sc_dip, CE_CONT,
faceed938d6ba7344a332694084d213905e93375fei feng - Sun Microsystems - Beijing China "ipw2200_stop(): exit\n"));
bb5e3b2f129cc39517b925419c22f69a378ec023eh}
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic int
bb5e3b2f129cc39517b925419c22f69a378ec023ehipw2200_config(struct ipw2200_softc *sc)
bb5e3b2f129cc39517b925419c22f69a378ec023eh{
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct ieee80211com *ic = &sc->sc_ic;
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct ipw2200_configuration cfg;
bb5e3b2f129cc39517b925419c22f69a378ec023eh uint32_t data;
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct ipw2200_txpower pwr;
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct ipw2200_rateset rs;
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct ipw2200_wep_key wkey;
bb5e3b2f129cc39517b925419c22f69a378ec023eh int err, i;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * Set the IBSS mode channel: Tx power
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (ic->ic_opmode == IEEE80211_M_IBSS) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh pwr.mode = IPW2200_MODE_11B;
bb5e3b2f129cc39517b925419c22f69a378ec023eh pwr.nchan = 11;
bb5e3b2f129cc39517b925419c22f69a378ec023eh for (i = 0; i < pwr.nchan; i++) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh pwr.chan[i].chan = i + 1;
bb5e3b2f129cc39517b925419c22f69a378ec023eh pwr.chan[i].power = IPW2200_TXPOWER_MAX;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_DBG(IPW2200_DBG_WIFI, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2200_config(): Setting .11b channels Tx power\n"));
bb5e3b2f129cc39517b925419c22f69a378ec023eh err = ipw2200_cmd(sc, IPW2200_CMD_SET_TX_POWER,
bb5e3b2f129cc39517b925419c22f69a378ec023eh &pwr, sizeof (pwr), 0);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (err != DDI_SUCCESS)
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (err);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh pwr.mode = IPW2200_MODE_11G;
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_DBG(IPW2200_DBG_WIFI, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2200_config(): Setting .11g channels Tx power\n"));
bb5e3b2f129cc39517b925419c22f69a378ec023eh err = ipw2200_cmd(sc, IPW2200_CMD_SET_TX_POWER,
bb5e3b2f129cc39517b925419c22f69a378ec023eh &pwr, sizeof (pwr), 0);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (err != DDI_SUCCESS)
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (err);
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * Set MAC address
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_DBG(IPW2200_DBG_WIFI, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2200_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 = ipw2200_cmd(sc, IPW2200_CMD_SET_MAC_ADDRESS, ic->ic_macaddr,
bb5e3b2f129cc39517b925419c22f69a378ec023eh IEEE80211_ADDR_LEN, 0);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (err != DDI_SUCCESS)
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (err);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * Set basic system config settings: configuration(capabilities)
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh (void) memset(&cfg, 0, sizeof (cfg));
bb5e3b2f129cc39517b925419c22f69a378ec023eh cfg.bluetooth_coexistence = 1;
bb5e3b2f129cc39517b925419c22f69a378ec023eh cfg.multicast_enabled = 1;
bb5e3b2f129cc39517b925419c22f69a378ec023eh cfg.answer_pbreq = 1;
bb5e3b2f129cc39517b925419c22f69a378ec023eh cfg.noise_reported = 1;
924f3e72988efae04c4357a6686a06ba300bab18eh cfg.disable_multicast_decryption = 1; /* WPA */
924f3e72988efae04c4357a6686a06ba300bab18eh cfg.disable_unicast_decryption = 1; /* WPA */
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_DBG(IPW2200_DBG_WIFI, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2200_config(): Configuring adapter\n"));
bb5e3b2f129cc39517b925419c22f69a378ec023eh err = ipw2200_cmd(sc, IPW2200_CMD_SET_CONFIG,
bb5e3b2f129cc39517b925419c22f69a378ec023eh &cfg, sizeof (cfg), 0);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (err != DDI_SUCCESS)
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (err);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * Set power mode
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh data = LE_32(IPW2200_POWER_MODE_CAM);
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_DBG(IPW2200_DBG_WIFI, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2200_config(): Setting power mode to %u\n", LE_32(data)));
bb5e3b2f129cc39517b925419c22f69a378ec023eh err = ipw2200_cmd(sc, IPW2200_CMD_SET_POWER_MODE,
bb5e3b2f129cc39517b925419c22f69a378ec023eh &data, sizeof (data), 0);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (err != DDI_SUCCESS)
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (err);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * Set supported rates
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh rs.mode = IPW2200_MODE_11G;
bb5e3b2f129cc39517b925419c22f69a378ec023eh rs.type = IPW2200_RATESET_TYPE_SUPPORTED;
bb5e3b2f129cc39517b925419c22f69a378ec023eh rs.nrates = ic->ic_sup_rates[IEEE80211_MODE_11G].ir_nrates;
bb5e3b2f129cc39517b925419c22f69a378ec023eh (void) memcpy(rs.rates, ic->ic_sup_rates[IEEE80211_MODE_11G].ir_rates,
bb5e3b2f129cc39517b925419c22f69a378ec023eh rs.nrates);
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_DBG(IPW2200_DBG_WIFI, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2200_config(): Setting .11g supported rates(%u)\n", rs.nrates));
bb5e3b2f129cc39517b925419c22f69a378ec023eh err = ipw2200_cmd(sc, IPW2200_CMD_SET_RATES, &rs, sizeof (rs), 0);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (err != DDI_SUCCESS)
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (err);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh rs.mode = IPW2200_MODE_11A;
bb5e3b2f129cc39517b925419c22f69a378ec023eh rs.type = IPW2200_RATESET_TYPE_SUPPORTED;
bb5e3b2f129cc39517b925419c22f69a378ec023eh rs.nrates = ic->ic_sup_rates[IEEE80211_MODE_11A].ir_nrates;
bb5e3b2f129cc39517b925419c22f69a378ec023eh (void) memcpy(rs.rates, ic->ic_sup_rates[IEEE80211_MODE_11A].ir_rates,
bb5e3b2f129cc39517b925419c22f69a378ec023eh rs.nrates);
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_DBG(IPW2200_DBG_WIFI, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2200_config(): Setting .11a supported rates(%u)\n", rs.nrates));
bb5e3b2f129cc39517b925419c22f69a378ec023eh err = ipw2200_cmd(sc, IPW2200_CMD_SET_RATES, &rs, sizeof (rs), 0);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (err != DDI_SUCCESS)
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (err);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * Set RTS(request-to-send) threshold
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh data = LE_32(ic->ic_rtsthreshold);
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_DBG(IPW2200_DBG_WIFI, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2200_config(): Setting RTS threshold to %u\n", LE_32(data)));
bb5e3b2f129cc39517b925419c22f69a378ec023eh err = ipw2200_cmd(sc, IPW2200_CMD_SET_RTS_THRESHOLD, &data,
bb5e3b2f129cc39517b925419c22f69a378ec023eh sizeof (data), 0);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (err != DDI_SUCCESS)
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (err);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * Set fragmentation threshold
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh data = LE_32(ic->ic_fragthreshold);
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_DBG(IPW2200_DBG_WIFI, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2200_config(): Setting fragmentation threshold to %u\n",
bb5e3b2f129cc39517b925419c22f69a378ec023eh LE_32(data)));
bb5e3b2f129cc39517b925419c22f69a378ec023eh err = ipw2200_cmd(sc, IPW2200_CMD_SET_FRAG_THRESHOLD, &data,
bb5e3b2f129cc39517b925419c22f69a378ec023eh sizeof (data), 0);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (err != DDI_SUCCESS)
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (err);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * Set desired ESSID if we have
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (ic->ic_des_esslen != 0) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_DBG(IPW2200_DBG_WIFI, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2200_config(): Setting desired ESSID to "
bb5e3b2f129cc39517b925419c22f69a378ec023eh "(%u),%c%c%c%c%c%c%c%c\n",
bb5e3b2f129cc39517b925419c22f69a378ec023eh ic->ic_des_esslen,
bb5e3b2f129cc39517b925419c22f69a378ec023eh ic->ic_des_essid[0], ic->ic_des_essid[1],
bb5e3b2f129cc39517b925419c22f69a378ec023eh ic->ic_des_essid[2], ic->ic_des_essid[3],
bb5e3b2f129cc39517b925419c22f69a378ec023eh ic->ic_des_essid[4], ic->ic_des_essid[5],
bb5e3b2f129cc39517b925419c22f69a378ec023eh ic->ic_des_essid[6], ic->ic_des_essid[7]));
bb5e3b2f129cc39517b925419c22f69a378ec023eh err = ipw2200_cmd(sc, IPW2200_CMD_SET_ESSID, ic->ic_des_essid,
bb5e3b2f129cc39517b925419c22f69a378ec023eh ic->ic_des_esslen, 0);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (err != DDI_SUCCESS)
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (err);
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * Set WEP initial vector(random seed)
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh (void) random_get_pseudo_bytes((uint8_t *)&data, sizeof (data));
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_DBG(IPW2200_DBG_WIFI, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2200_config(): Setting initialization vector to %u\n",
bb5e3b2f129cc39517b925419c22f69a378ec023eh LE_32(data)));
bb5e3b2f129cc39517b925419c22f69a378ec023eh err = ipw2200_cmd(sc, IPW2200_CMD_SET_IV, &data, sizeof (data), 0);
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 IPW2200_DBG(IPW2200_DBG_WIFI, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2200_config(): Setting Wep Key\n", LE_32(data)));
bb5e3b2f129cc39517b925419c22f69a378ec023eh for (i = 0; i < IEEE80211_WEP_NKID; i++) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh wkey.cmd = IPW2200_WEP_KEY_CMD_SETKEY;
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 = ipw2200_cmd(sc, IPW2200_CMD_SET_WEP_KEY,
bb5e3b2f129cc39517b925419c22f69a378ec023eh &wkey, sizeof (wkey), 0);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (err != DDI_SUCCESS)
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (err);
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_DBG(IPW2200_DBG_WIFI, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2200_config(): Enabling adapter\n"));
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (ipw2200_cmd(sc, IPW2200_CMD_ENABLE, NULL, 0, 0));
bb5e3b2f129cc39517b925419c22f69a378ec023eh}
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic int
bb5e3b2f129cc39517b925419c22f69a378ec023ehipw2200_cmd(struct ipw2200_softc *sc,
bb5e3b2f129cc39517b925419c22f69a378ec023eh uint32_t type, void *buf, size_t len, int async)
bb5e3b2f129cc39517b925419c22f69a378ec023eh{
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct ipw2200_cmd_desc *cmd;
bb5e3b2f129cc39517b925419c22f69a378ec023eh clock_t clk;
bb5e3b2f129cc39517b925419c22f69a378ec023eh uint32_t idx;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh mutex_enter(&sc->sc_cmd_lock);
bb5e3b2f129cc39517b925419c22f69a378ec023eh while (sc->sc_cmd_free < 1)
bb5e3b2f129cc39517b925419c22f69a378ec023eh cv_wait(&sc->sc_cmd_cond, &sc->sc_cmd_lock);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh idx = sc->sc_cmd_cur;
bb5e3b2f129cc39517b925419c22f69a378ec023eh cmd = &sc->sc_cmdsc[idx];
bb5e3b2f129cc39517b925419c22f69a378ec023eh (void) memset(cmd, 0, sizeof (*cmd));
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_DBG(IPW2200_DBG_RING, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2200_cmd(): cmd-cur=%d\n", idx));
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh cmd->hdr.type = IPW2200_HDR_TYPE_COMMAND;
bb5e3b2f129cc39517b925419c22f69a378ec023eh cmd->hdr.flags = IPW2200_HDR_FLAG_IRQ;
bb5e3b2f129cc39517b925419c22f69a378ec023eh cmd->type = (uint8_t)type;
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (len == 0 || buf == NULL)
bb5e3b2f129cc39517b925419c22f69a378ec023eh cmd->len = 0;
bb5e3b2f129cc39517b925419c22f69a378ec023eh else {
bb5e3b2f129cc39517b925419c22f69a378ec023eh cmd->len = (uint8_t)len;
bb5e3b2f129cc39517b925419c22f69a378ec023eh (void) memcpy(cmd->data, buf, len);
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_done[idx] = 0;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * DMA sync
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh (void) ddi_dma_sync(sc->sc_dma_cmdsc.dr_hnd,
bb5e3b2f129cc39517b925419c22f69a378ec023eh idx * sizeof (struct ipw2200_cmd_desc),
bb5e3b2f129cc39517b925419c22f69a378ec023eh sizeof (struct ipw2200_cmd_desc), DDI_DMA_SYNC_FORDEV);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_cmd_cur = RING_FORWARD(sc->sc_cmd_cur, 1, IPW2200_CMD_RING_SIZE);
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_cmd_free--;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2200_csr_put32(sc, IPW2200_CSR_CMD_WRITE_INDEX, sc->sc_cmd_cur);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh mutex_exit(&sc->sc_cmd_lock);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (async)
bb5e3b2f129cc39517b925419c22f69a378ec023eh goto out;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * Wait for command done
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni clk = drv_usectohz(5000000);
bb5e3b2f129cc39517b925419c22f69a378ec023eh mutex_enter(&sc->sc_ilock);
bb5e3b2f129cc39517b925419c22f69a378ec023eh while (sc->sc_done[idx] == 0) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh /* pending */
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni if (cv_reltimedwait(&sc->sc_cmd_status_cond, &sc->sc_ilock,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni clk, TR_CLOCK_TICK) < 0)
bb5e3b2f129cc39517b925419c22f69a378ec023eh break;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh mutex_exit(&sc->sc_ilock);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_DBG(IPW2200_DBG_RING, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2200_cmd(): cmd-done=%s\n", sc->sc_done[idx] ? "yes" : "no"));
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (sc->sc_done[idx] == 0)
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (DDI_FAILURE);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023ehout:
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (DDI_SUCCESS);
bb5e3b2f129cc39517b925419c22f69a378ec023eh}
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh/*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * If init failed, it will call stop internally. Therefore, it's unnecessary
bb5e3b2f129cc39517b925419c22f69a378ec023eh * to call ipw2200_stop() when this subroutine is failed. Otherwise, it may
bb5e3b2f129cc39517b925419c22f69a378ec023eh * be called twice.
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023ehint
bb5e3b2f129cc39517b925419c22f69a378ec023ehipw2200_init(struct ipw2200_softc *sc)
bb5e3b2f129cc39517b925419c22f69a378ec023eh{
bb5e3b2f129cc39517b925419c22f69a378ec023eh int err;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * No firmware is available, failed
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (!(sc->sc_flags & IPW2200_FLAG_FW_CACHED)) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_WARN((sc->sc_dip, CE_WARN,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2200_init(): no firmware is available\n"));
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (DDI_FAILURE); /* return directly */
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2200_stop(sc);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh err = ipw2200_chip_reset(sc);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (err != DDI_SUCCESS) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_WARN((sc->sc_dip, CE_WARN,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2200_init(): could not reset adapter\n"));
bb5e3b2f129cc39517b925419c22f69a378ec023eh goto fail;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * Load boot code
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh err = ipw2200_load_fw(sc, sc->sc_fw.boot_base, sc->sc_fw.boot_size);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (err != DDI_SUCCESS) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_WARN((sc->sc_dip, CE_WARN,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2200_init(): could not load boot code\n"));
bb5e3b2f129cc39517b925419c22f69a378ec023eh goto fail;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * Load boot microcode
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh err = ipw2200_load_uc(sc, sc->sc_fw.uc_base, sc->sc_fw.uc_size);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (err != DDI_SUCCESS) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_WARN((sc->sc_dip, CE_WARN,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2200_init(): could not load microcode\n"));
bb5e3b2f129cc39517b925419c22f69a378ec023eh goto fail;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2200_master_stop(sc);
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2200_ring_hwsetup(sc);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * Load firmware
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh err = ipw2200_load_fw(sc, sc->sc_fw.fw_base, sc->sc_fw.fw_size);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (err != DDI_SUCCESS) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_WARN((sc->sc_dip, CE_WARN,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2200_init(): could not load firmware\n"));
bb5e3b2f129cc39517b925419c22f69a378ec023eh goto fail;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_flags |= IPW2200_FLAG_FW_INITED;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * Hardware will be enabled after configuration
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh err = ipw2200_config(sc);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (err != DDI_SUCCESS) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_WARN((sc->sc_dip, CE_WARN,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2200_init(): device configuration failed\n"));
bb5e3b2f129cc39517b925419c22f69a378ec023eh goto fail;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * workround to prevent too many h/w error.
bb5e3b2f129cc39517b925419c22f69a378ec023eh * delay for a while till h/w is stable.
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh delay(drv_usectohz(delay_config_stable));
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (DDI_SUCCESS); /* return successfully */
bb5e3b2f129cc39517b925419c22f69a378ec023ehfail:
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2200_stop(sc);
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (err);
bb5e3b2f129cc39517b925419c22f69a378ec023eh}
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh/*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * get hardware configurations from EEPROM embedded within PRO/2200
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic void
bb5e3b2f129cc39517b925419c22f69a378ec023ehipw2200_hwconf_get(struct ipw2200_softc *sc)
bb5e3b2f129cc39517b925419c22f69a378ec023eh{
bb5e3b2f129cc39517b925419c22f69a378ec023eh int i;
bb5e3b2f129cc39517b925419c22f69a378ec023eh uint16_t val;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * Get mac address
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh i = 0;
bb5e3b2f129cc39517b925419c22f69a378ec023eh val = ipw2200_rom_get16(sc, IPW2200_EEPROM_MAC + 0);
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_macaddr[i++] = val >> 8;
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_macaddr[i++] = val & 0xff;
bb5e3b2f129cc39517b925419c22f69a378ec023eh val = ipw2200_rom_get16(sc, IPW2200_EEPROM_MAC + 1);
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_macaddr[i++] = val >> 8;
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_macaddr[i++] = val & 0xff;
bb5e3b2f129cc39517b925419c22f69a378ec023eh val = ipw2200_rom_get16(sc, IPW2200_EEPROM_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),
bb5e3b2f129cc39517b925419c22f69a378ec023eh "%02x:%02x:%02x:%02x:%02x:%02x",
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_macaddr[0], sc->sc_macaddr[1],
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_macaddr[2], sc->sc_macaddr[3],
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_macaddr[4], sc->sc_macaddr[5]);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh}
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh/*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * all ipw2200 interrupts will be masked by this routine
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic void
bb5e3b2f129cc39517b925419c22f69a378ec023ehipw2200_master_stop(struct ipw2200_softc *sc)
bb5e3b2f129cc39517b925419c22f69a378ec023eh{
bb5e3b2f129cc39517b925419c22f69a378ec023eh int ntries;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * disable interrupts
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2200_csr_put32(sc, IPW2200_CSR_INTR_MASK, 0);
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2200_csr_put32(sc, IPW2200_CSR_RST, IPW2200_RST_STOP_MASTER);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * wait long enough to ensure hardware stop successfully.
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh for (ntries = 0; ntries < 500; ntries++) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (ipw2200_csr_get32(sc, IPW2200_CSR_RST) &
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_RST_MASTER_DISABLED)
bb5e3b2f129cc39517b925419c22f69a378ec023eh break;
bb5e3b2f129cc39517b925419c22f69a378ec023eh /* wait for a while */
bb5e3b2f129cc39517b925419c22f69a378ec023eh drv_usecwait(100);
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
faceed938d6ba7344a332694084d213905e93375fei feng - Sun Microsystems - Beijing China if (ntries == 500)
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_WARN((sc->sc_dip, CE_WARN,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2200_master_stop(): timeout\n"));
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2200_csr_put32(sc, IPW2200_CSR_RST,
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_RST_PRINCETON_RESET |
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2200_csr_get32(sc, IPW2200_CSR_RST));
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_flags &= ~IPW2200_FLAG_FW_INITED;
bb5e3b2f129cc39517b925419c22f69a378ec023eh}
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh/*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * all ipw2200 interrupts will be masked by this routine
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic int
bb5e3b2f129cc39517b925419c22f69a378ec023ehipw2200_chip_reset(struct ipw2200_softc *sc)
bb5e3b2f129cc39517b925419c22f69a378ec023eh{
bb5e3b2f129cc39517b925419c22f69a378ec023eh uint32_t tmp;
bb5e3b2f129cc39517b925419c22f69a378ec023eh int ntries, i;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2200_master_stop(sc);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * Move adapter to DO state
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh tmp = ipw2200_csr_get32(sc, IPW2200_CSR_CTL);
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2200_csr_put32(sc, IPW2200_CSR_CTL, tmp | IPW2200_CTL_INIT);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * Initialize Phase-Locked Level (PLL)
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2200_csr_put32(sc, IPW2200_CSR_READ_INT, IPW2200_READ_INT_INIT_HOST);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * Wait for clock stabilization
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh for (ntries = 0; ntries < 1000; ntries++) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (ipw2200_csr_get32(sc, IPW2200_CSR_CTL) &
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_CTL_CLOCK_READY)
bb5e3b2f129cc39517b925419c22f69a378ec023eh break;
bb5e3b2f129cc39517b925419c22f69a378ec023eh drv_usecwait(200);
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (ntries == 1000) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_WARN((sc->sc_dip, CE_WARN,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2200_chip_reset(): timeout\n"));
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (DDI_FAILURE);
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh tmp = ipw2200_csr_get32(sc, IPW2200_CSR_RST);
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2200_csr_put32(sc, IPW2200_CSR_RST, tmp | IPW2200_RST_SW_RESET);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh drv_usecwait(10);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh tmp = ipw2200_csr_get32(sc, IPW2200_CSR_CTL);
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2200_csr_put32(sc, IPW2200_CSR_CTL, tmp | IPW2200_CTL_INIT);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * clear NIC memory
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2200_csr_put32(sc, IPW2200_CSR_AUTOINC_ADDR, 0);
bb5e3b2f129cc39517b925419c22f69a378ec023eh for (i = 0; i < 0xc000; i++)
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2200_csr_put32(sc, IPW2200_CSR_AUTOINC_DATA, 0);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (DDI_SUCCESS);
bb5e3b2f129cc39517b925419c22f69a378ec023eh}
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh/*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * This function is used by wificonfig/dladm to get the current
bb5e3b2f129cc39517b925419c22f69a378ec023eh * radio status, it is off/on
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023ehint
bb5e3b2f129cc39517b925419c22f69a378ec023ehipw2200_radio_status(struct ipw2200_softc *sc)
bb5e3b2f129cc39517b925419c22f69a378ec023eh{
bb5e3b2f129cc39517b925419c22f69a378ec023eh int val;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh val = (ipw2200_csr_get32(sc, IPW2200_CSR_IO) &
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_IO_RADIO_ENABLED) ? 1 : 0;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (val);
bb5e3b2f129cc39517b925419c22f69a378ec023eh}
bb5e3b2f129cc39517b925419c22f69a378ec023eh/*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * This function is used to get the statistic
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023ehvoid
bb5e3b2f129cc39517b925419c22f69a378ec023ehipw2200_get_statistics(struct ipw2200_softc *sc)
bb5e3b2f129cc39517b925419c22f69a378ec023eh{
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct ieee80211com *ic = &sc->sc_ic;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh uint32_t size, buf[128];
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (!(sc->sc_flags & IPW2200_FLAG_FW_INITED)) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_DBG(IPW2200_DBG_IOCTL, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2200_get_statistic(): fw doesn't download yet."));
bb5e3b2f129cc39517b925419c22f69a378ec023eh return;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh size = min(ipw2200_csr_get32(sc, IPW2200_CSR_TABLE0_SIZE), 128 - 1);
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2200_csr_getbuf32(sc, IPW2200_CSR_TABLE0_BASE, &buf[1], size);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * To retrieve the statistic information into proper places. There are
bb5e3b2f129cc39517b925419c22f69a378ec023eh * lot of information. These table will be read once a second.
bb5e3b2f129cc39517b925419c22f69a378ec023eh * Hopefully, it will not effect the performance.
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * For the tx/crc information, we can get them from chip directly;
bb5e3b2f129cc39517b925419c22f69a378ec023eh * For the rx/wep error/(rts) related information, leave them net80211.
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh /* WIFI_STAT_TX_FRAGS */
bb5e3b2f129cc39517b925419c22f69a378ec023eh ic->ic_stats.is_tx_frags = (uint32_t)buf[5];
bb5e3b2f129cc39517b925419c22f69a378ec023eh /* WIFI_STAT_MCAST_TX */
bb5e3b2f129cc39517b925419c22f69a378ec023eh ic->ic_stats.is_tx_mcast = (uint32_t)buf[31];
bb5e3b2f129cc39517b925419c22f69a378ec023eh /* WIFI_STAT_TX_RETRANS */
bb5e3b2f129cc39517b925419c22f69a378ec023eh ic->ic_stats.is_tx_retries = (uint32_t)buf[56];
bb5e3b2f129cc39517b925419c22f69a378ec023eh /* WIFI_STAT_TX_FAILED */
bb5e3b2f129cc39517b925419c22f69a378ec023eh ic->ic_stats.is_tx_failed = (uint32_t)buf[57];
bb5e3b2f129cc39517b925419c22f69a378ec023eh /* MAC_STAT_OBYTES */
bb5e3b2f129cc39517b925419c22f69a378ec023eh ic->ic_stats.is_tx_bytes = (uint32_t)buf[64];
bb5e3b2f129cc39517b925419c22f69a378ec023eh}
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh/*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * DMA region alloc subroutine
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023ehint
bb5e3b2f129cc39517b925419c22f69a378ec023ehipw2200_dma_region_alloc(struct ipw2200_softc *sc, struct dma_region *dr,
bb5e3b2f129cc39517b925419c22f69a378ec023eh size_t size, uint_t dir, uint_t flags)
bb5e3b2f129cc39517b925419c22f69a378ec023eh{
bb5e3b2f129cc39517b925419c22f69a378ec023eh dev_info_t *dip = sc->sc_dip;
bb5e3b2f129cc39517b925419c22f69a378ec023eh int err;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_DBG(IPW2200_DBG_DMA, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2200_dma_region_alloc(): size =%u\n", size));
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh err = ddi_dma_alloc_handle(dip, &ipw2200_dma_attr, DDI_DMA_SLEEP, NULL,
bb5e3b2f129cc39517b925419c22f69a378ec023eh &dr->dr_hnd);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (err != DDI_SUCCESS) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_DBG(IPW2200_DBG_DMA, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2200_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, &ipw2200_dma_accattr,
bb5e3b2f129cc39517b925419c22f69a378ec023eh flags, DDI_DMA_SLEEP, NULL,
bb5e3b2f129cc39517b925419c22f69a378ec023eh &dr->dr_base, &dr->dr_size, &dr->dr_acc);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (err != DDI_SUCCESS) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_DBG(IPW2200_DBG_DMA, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2200_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,
bb5e3b2f129cc39517b925419c22f69a378ec023eh dir | flags, DDI_DMA_SLEEP, NULL,
bb5e3b2f129cc39517b925419c22f69a378ec023eh &dr->dr_cookie, &dr->dr_ccnt);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (err != DDI_DMA_MAPPED) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_DBG(IPW2200_DBG_DMA, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2200_dma_region_alloc(): "
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ddi_dma_addr_bind_handle() failed\n"));
bb5e3b2f129cc39517b925419c22f69a378ec023eh goto fail2;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_DBG(IPW2200_DBG_DMA, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2200_dma_region_alloc(): ccnt=%u\n", dr->dr_ccnt));
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (dr->dr_ccnt != 1) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh err = DDI_FAILURE;
bb5e3b2f129cc39517b925419c22f69a378ec023eh goto fail3;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh dr->dr_pbase = dr->dr_cookie.dmac_address;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_DBG(IPW2200_DBG_DMA, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2200_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
bb5e3b2f129cc39517b925419c22f69a378ec023ehvoid
bb5e3b2f129cc39517b925419c22f69a378ec023ehipw2200_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
bb5e3b2f129cc39517b925419c22f69a378ec023ehipw2200_ring_alloc(struct ipw2200_softc *sc)
bb5e3b2f129cc39517b925419c22f69a378ec023eh{
bb5e3b2f129cc39517b925419c22f69a378ec023eh int err, i;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * tx desc ring
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_dma_txdsc.dr_name = "ipw2200-tx-desc-ring";
bb5e3b2f129cc39517b925419c22f69a378ec023eh err = ipw2200_dma_region_alloc(sc, &sc->sc_dma_txdsc,
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_TX_RING_SIZE * sizeof (struct ipw2200_tx_desc),
bb5e3b2f129cc39517b925419c22f69a378ec023eh DDI_DMA_WRITE, DDI_DMA_CONSISTENT);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (err != DDI_SUCCESS)
bb5e3b2f129cc39517b925419c22f69a378ec023eh goto fail0;
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * tx buffer array
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh for (i = 0; i < IPW2200_TX_RING_SIZE; i++) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_dma_txbufs[i].dr_name = "ipw2200-tx-buf";
bb5e3b2f129cc39517b925419c22f69a378ec023eh err = ipw2200_dma_region_alloc(sc, &sc->sc_dma_txbufs[i],
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_TXBUF_SIZE, DDI_DMA_WRITE, DDI_DMA_STREAMING);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (err != DDI_SUCCESS) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh while (i >= 0) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2200_dma_region_free(&sc->sc_dma_txbufs[i]);
bb5e3b2f129cc39517b925419c22f69a378ec023eh i--;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh goto fail1;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * rx buffer array
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh for (i = 0; i < IPW2200_RX_RING_SIZE; i++) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_dma_rxbufs[i].dr_name = "ipw2200-rx-buf";
bb5e3b2f129cc39517b925419c22f69a378ec023eh err = ipw2200_dma_region_alloc(sc, &sc->sc_dma_rxbufs[i],
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_RXBUF_SIZE, DDI_DMA_READ, DDI_DMA_STREAMING);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (err != DDI_SUCCESS) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh while (i >= 0) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2200_dma_region_free(&sc->sc_dma_rxbufs[i]);
bb5e3b2f129cc39517b925419c22f69a378ec023eh i--;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh goto fail2;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * cmd desc ring
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_dma_cmdsc.dr_name = "ipw2200-cmd-desc-ring";
bb5e3b2f129cc39517b925419c22f69a378ec023eh err = ipw2200_dma_region_alloc(sc, &sc->sc_dma_cmdsc,
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_CMD_RING_SIZE * sizeof (struct ipw2200_cmd_desc),
bb5e3b2f129cc39517b925419c22f69a378ec023eh DDI_DMA_WRITE, DDI_DMA_CONSISTENT);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (err != DDI_SUCCESS)
bb5e3b2f129cc39517b925419c22f69a378ec023eh goto fail3;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (DDI_SUCCESS);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023ehfail3:
bb5e3b2f129cc39517b925419c22f69a378ec023eh for (i = 0; i < IPW2200_RX_RING_SIZE; i++)
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2200_dma_region_free(&sc->sc_dma_rxbufs[i]);
bb5e3b2f129cc39517b925419c22f69a378ec023ehfail2:
bb5e3b2f129cc39517b925419c22f69a378ec023eh for (i = 0; i < IPW2200_TX_RING_SIZE; i++)
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2200_dma_region_free(&sc->sc_dma_txbufs[i]);
bb5e3b2f129cc39517b925419c22f69a378ec023ehfail1:
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2200_dma_region_free(&sc->sc_dma_txdsc);
bb5e3b2f129cc39517b925419c22f69a378ec023ehfail0:
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (err);
bb5e3b2f129cc39517b925419c22f69a378ec023eh}
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic void
bb5e3b2f129cc39517b925419c22f69a378ec023ehipw2200_ring_free(struct ipw2200_softc *sc)
bb5e3b2f129cc39517b925419c22f69a378ec023eh{
bb5e3b2f129cc39517b925419c22f69a378ec023eh int i;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * tx ring desc
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2200_dma_region_free(&sc->sc_dma_txdsc);
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * tx buf
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh for (i = 0; i < IPW2200_TX_RING_SIZE; i++)
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2200_dma_region_free(&sc->sc_dma_txbufs[i]);
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * rx buf
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh for (i = 0; i < IPW2200_RX_RING_SIZE; i++)
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2200_dma_region_free(&sc->sc_dma_rxbufs[i]);
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * command ring desc
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2200_dma_region_free(&sc->sc_dma_cmdsc);
bb5e3b2f129cc39517b925419c22f69a378ec023eh}
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic void
bb5e3b2f129cc39517b925419c22f69a378ec023ehipw2200_ring_reset(struct ipw2200_softc *sc)
bb5e3b2f129cc39517b925419c22f69a378ec023eh{
bb5e3b2f129cc39517b925419c22f69a378ec023eh int i;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * tx desc ring & buffer array
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_tx_cur = 0;
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_tx_free = IPW2200_TX_RING_SIZE;
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_txdsc = (struct ipw2200_tx_desc *)sc->sc_dma_txdsc.dr_base;
bb5e3b2f129cc39517b925419c22f69a378ec023eh for (i = 0; i < IPW2200_TX_RING_SIZE; i++)
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_txbufs[i] = (uint8_t *)sc->sc_dma_txbufs[i].dr_base;
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * rx buffer array
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_rx_cur = 0;
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_rx_free = IPW2200_RX_RING_SIZE;
bb5e3b2f129cc39517b925419c22f69a378ec023eh for (i = 0; i < IPW2200_RX_RING_SIZE; i++)
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_rxbufs[i] = (uint8_t *)sc->sc_dma_rxbufs[i].dr_base;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * command desc ring
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_cmd_cur = 0;
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_cmd_free = IPW2200_CMD_RING_SIZE;
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_cmdsc = (struct ipw2200_cmd_desc *)sc->sc_dma_cmdsc.dr_base;
bb5e3b2f129cc39517b925419c22f69a378ec023eh}
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh/*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * tx, rx rings and command initialization
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic int
bb5e3b2f129cc39517b925419c22f69a378ec023ehipw2200_ring_init(struct ipw2200_softc *sc)
bb5e3b2f129cc39517b925419c22f69a378ec023eh{
bb5e3b2f129cc39517b925419c22f69a378ec023eh int err;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh err = ipw2200_ring_alloc(sc);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (err != DDI_SUCCESS)
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (err);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2200_ring_reset(sc);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (DDI_SUCCESS);
bb5e3b2f129cc39517b925419c22f69a378ec023eh}
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic void
bb5e3b2f129cc39517b925419c22f69a378ec023ehipw2200_ring_hwsetup(struct ipw2200_softc *sc)
bb5e3b2f129cc39517b925419c22f69a378ec023eh{
bb5e3b2f129cc39517b925419c22f69a378ec023eh int i;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * command desc ring
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2200_csr_put32(sc, IPW2200_CSR_CMD_BASE, sc->sc_dma_cmdsc.dr_pbase);
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2200_csr_put32(sc, IPW2200_CSR_CMD_SIZE, IPW2200_CMD_RING_SIZE);
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2200_csr_put32(sc, IPW2200_CSR_CMD_WRITE_INDEX, sc->sc_cmd_cur);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * tx desc ring. only tx1 is used, tx2, tx3, and tx4 are unused
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2200_csr_put32(sc, IPW2200_CSR_TX1_BASE, sc->sc_dma_txdsc.dr_pbase);
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2200_csr_put32(sc, IPW2200_CSR_TX1_SIZE, IPW2200_TX_RING_SIZE);
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2200_csr_put32(sc, IPW2200_CSR_TX1_WRITE_INDEX, sc->sc_tx_cur);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * tx2, tx3, tx4 is not used
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2200_csr_put32(sc, IPW2200_CSR_TX2_BASE, sc->sc_dma_txdsc.dr_pbase);
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2200_csr_put32(sc, IPW2200_CSR_TX2_SIZE, IPW2200_TX_RING_SIZE);
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2200_csr_put32(sc, IPW2200_CSR_TX2_READ_INDEX, 0);
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2200_csr_put32(sc, IPW2200_CSR_TX2_WRITE_INDEX, 0);
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2200_csr_put32(sc, IPW2200_CSR_TX3_BASE, sc->sc_dma_txdsc.dr_pbase);
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2200_csr_put32(sc, IPW2200_CSR_TX3_SIZE, IPW2200_TX_RING_SIZE);
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2200_csr_put32(sc, IPW2200_CSR_TX3_READ_INDEX, 0);
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2200_csr_put32(sc, IPW2200_CSR_TX3_WRITE_INDEX, 0);
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2200_csr_put32(sc, IPW2200_CSR_TX4_BASE, sc->sc_dma_txdsc.dr_pbase);
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2200_csr_put32(sc, IPW2200_CSR_TX4_SIZE, IPW2200_TX_RING_SIZE);
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2200_csr_put32(sc, IPW2200_CSR_TX4_READ_INDEX, 0);
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2200_csr_put32(sc, IPW2200_CSR_TX4_WRITE_INDEX, 0);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * rx buffer ring
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh for (i = 0; i < IPW2200_RX_RING_SIZE; i++)
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2200_csr_put32(sc, IPW2200_CSR_RX_BASE + i * 4,
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_dma_rxbufs[i].dr_pbase);
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * all rx buffer are empty, rx-rd-index == 0 && rx-wr-index == N-1
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2200_csr_put32(sc, IPW2200_CSR_RX_WRITE_INDEX,
bb5e3b2f129cc39517b925419c22f69a378ec023eh RING_BACKWARD(sc->sc_rx_cur, 1, IPW2200_RX_RING_SIZE));
bb5e3b2f129cc39517b925419c22f69a378ec023eh}
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023ehint
bb5e3b2f129cc39517b925419c22f69a378ec023ehipw2200_start_scan(struct ipw2200_softc *sc)
bb5e3b2f129cc39517b925419c22f69a378ec023eh{
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct ieee80211com *ic = &sc->sc_ic;
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct ipw2200_scan scan;
bb5e3b2f129cc39517b925419c22f69a378ec023eh uint8_t *ch;
bb5e3b2f129cc39517b925419c22f69a378ec023eh int cnt, i;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_DBG(IPW2200_DBG_SCAN, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2200_start_scan(): start scanning \n"));
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * start scanning
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_flags |= IPW2200_FLAG_SCANNING;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh (void) memset(&scan, 0, sizeof (scan));
bb5e3b2f129cc39517b925419c22f69a378ec023eh scan.type = (ic->ic_des_esslen != 0) ? IPW2200_SCAN_TYPE_BDIRECTED :
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_SCAN_TYPE_BROADCAST;
bb5e3b2f129cc39517b925419c22f69a378ec023eh scan.dwelltime = LE_16(40); /* The interval is set up to 40 */
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * Compact supported channel number(5G) into a single buffer
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh ch = scan.channels;
bb5e3b2f129cc39517b925419c22f69a378ec023eh cnt = 0;
bb5e3b2f129cc39517b925419c22f69a378ec023eh for (i = 0; i <= IEEE80211_CHAN_MAX; i++) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (IEEE80211_IS_CHAN_5GHZ(&ic->ic_sup_channels[i]) &&
bb5e3b2f129cc39517b925419c22f69a378ec023eh isset(ic->ic_chan_active, i)) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh *++ch = (uint8_t)i;
bb5e3b2f129cc39517b925419c22f69a378ec023eh cnt++;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh *(ch - cnt) = IPW2200_CHAN_5GHZ | (uint8_t)cnt;
3b608f655bd09bfb0ba6b14bb23ec70acc77814cql ch = (cnt > 0) ? (ch + 1) : (scan.channels);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * Compact supported channel number(2G) into a single buffer
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh cnt = 0;
bb5e3b2f129cc39517b925419c22f69a378ec023eh for (i = 0; i <= IEEE80211_CHAN_MAX; i++) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (IEEE80211_IS_CHAN_2GHZ(&ic->ic_sup_channels[i]) &&
bb5e3b2f129cc39517b925419c22f69a378ec023eh isset(ic->ic_chan_active, i)) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh *++ch = (uint8_t)i;
bb5e3b2f129cc39517b925419c22f69a378ec023eh cnt++;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh *(ch - cnt) = IPW2200_CHAN_2GHZ | cnt;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (ipw2200_cmd(sc, IPW2200_CMD_SCAN, &scan, sizeof (scan), 1));
bb5e3b2f129cc39517b925419c22f69a378ec023eh}
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023ehint
bb5e3b2f129cc39517b925419c22f69a378ec023ehipw2200_auth_and_assoc(struct ipw2200_softc *sc)
bb5e3b2f129cc39517b925419c22f69a378ec023eh{
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct ieee80211com *ic = &sc->sc_ic;
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct ieee80211_node *in = ic->ic_bss;
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct ipw2200_configuration cfg;
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct ipw2200_rateset rs;
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct ipw2200_associate assoc;
bb5e3b2f129cc39517b925419c22f69a378ec023eh uint32_t data;
bb5e3b2f129cc39517b925419c22f69a378ec023eh int err;
924f3e72988efae04c4357a6686a06ba300bab18eh uint8_t *wpa_level;
924f3e72988efae04c4357a6686a06ba300bab18eh
924f3e72988efae04c4357a6686a06ba300bab18eh if (sc->sc_flags & IPW2200_FLAG_ASSOCIATED) {
924f3e72988efae04c4357a6686a06ba300bab18eh /* already associated */
924f3e72988efae04c4357a6686a06ba300bab18eh return (-1);
924f3e72988efae04c4357a6686a06ba300bab18eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * set the confiuration
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (IEEE80211_IS_CHAN_2GHZ(in->in_chan)) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh /* enable b/g auto-detection */
bb5e3b2f129cc39517b925419c22f69a378ec023eh (void) memset(&cfg, 0, sizeof (cfg));
bb5e3b2f129cc39517b925419c22f69a378ec023eh cfg.bluetooth_coexistence = 1;
bb5e3b2f129cc39517b925419c22f69a378ec023eh cfg.multicast_enabled = 1;
bb5e3b2f129cc39517b925419c22f69a378ec023eh cfg.use_protection = 1;
bb5e3b2f129cc39517b925419c22f69a378ec023eh cfg.answer_pbreq = 1;
bb5e3b2f129cc39517b925419c22f69a378ec023eh cfg.noise_reported = 1;
924f3e72988efae04c4357a6686a06ba300bab18eh cfg.disable_multicast_decryption = 1; /* WPA */
924f3e72988efae04c4357a6686a06ba300bab18eh cfg.disable_unicast_decryption = 1; /* WPA */
bb5e3b2f129cc39517b925419c22f69a378ec023eh err = ipw2200_cmd(sc, IPW2200_CMD_SET_CONFIG,
bb5e3b2f129cc39517b925419c22f69a378ec023eh &cfg, sizeof (cfg), 1);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (err != DDI_SUCCESS)
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (err);
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * set the essid, may be null/hidden AP
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_DBG(IPW2200_DBG_WIFI, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2200_auth_and_assoc(): "
bb5e3b2f129cc39517b925419c22f69a378ec023eh "setting ESSID to(%u),%c%c%c%c%c%c%c%c\n",
bb5e3b2f129cc39517b925419c22f69a378ec023eh in->in_esslen,
bb5e3b2f129cc39517b925419c22f69a378ec023eh in->in_essid[0], in->in_essid[1],
bb5e3b2f129cc39517b925419c22f69a378ec023eh in->in_essid[2], in->in_essid[3],
bb5e3b2f129cc39517b925419c22f69a378ec023eh in->in_essid[4], in->in_essid[5],
bb5e3b2f129cc39517b925419c22f69a378ec023eh in->in_essid[6], in->in_essid[7]));
bb5e3b2f129cc39517b925419c22f69a378ec023eh err = ipw2200_cmd(sc, IPW2200_CMD_SET_ESSID, in->in_essid,
bb5e3b2f129cc39517b925419c22f69a378ec023eh in->in_esslen, 1);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (err != DDI_SUCCESS)
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (err);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * set the rate: the rate set has already been ''negocitated''
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh rs.mode = IEEE80211_IS_CHAN_5GHZ(in->in_chan) ?
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_MODE_11A : IPW2200_MODE_11G;
bb5e3b2f129cc39517b925419c22f69a378ec023eh rs.type = IPW2200_RATESET_TYPE_NEGOCIATED;
bb5e3b2f129cc39517b925419c22f69a378ec023eh rs.nrates = in->in_rates.ir_nrates;
bb5e3b2f129cc39517b925419c22f69a378ec023eh (void) memcpy(rs.rates, in->in_rates.ir_rates, in->in_rates.ir_nrates);
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_DBG(IPW2200_DBG_WIFI, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2200_auth_and_assoc(): "
bb5e3b2f129cc39517b925419c22f69a378ec023eh "setting negotiated rates to(nrates = %u)\n", rs.nrates));
bb5e3b2f129cc39517b925419c22f69a378ec023eh err = ipw2200_cmd(sc, IPW2200_CMD_SET_RATES, &rs, sizeof (rs), 1);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (err != DDI_SUCCESS)
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (err);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
924f3e72988efae04c4357a6686a06ba300bab18eh /*
924f3e72988efae04c4357a6686a06ba300bab18eh * invoke command associate
924f3e72988efae04c4357a6686a06ba300bab18eh */
924f3e72988efae04c4357a6686a06ba300bab18eh (void) memset(&assoc, 0, sizeof (assoc));
924f3e72988efae04c4357a6686a06ba300bab18eh
924f3e72988efae04c4357a6686a06ba300bab18eh /*
924f3e72988efae04c4357a6686a06ba300bab18eh * set opt_ie to h/w if associated is WPA, opt_ie has been verified
924f3e72988efae04c4357a6686a06ba300bab18eh * by net80211 kernel module.
924f3e72988efae04c4357a6686a06ba300bab18eh */
924f3e72988efae04c4357a6686a06ba300bab18eh if (ic->ic_opt_ie != NULL) {
924f3e72988efae04c4357a6686a06ba300bab18eh
924f3e72988efae04c4357a6686a06ba300bab18eh wpa_level = (uint8_t *)ic->ic_opt_ie;
924f3e72988efae04c4357a6686a06ba300bab18eh
924f3e72988efae04c4357a6686a06ba300bab18eh IPW2200_DBG(IPW2200_DBG_WIFI, (sc->sc_dip, CE_CONT,
924f3e72988efae04c4357a6686a06ba300bab18eh "ipw2200_auth_and_assoc(): "
924f3e72988efae04c4357a6686a06ba300bab18eh "set wpa_ie and wpa_ie_len to h/w. "
924f3e72988efae04c4357a6686a06ba300bab18eh "length is %d\n"
924f3e72988efae04c4357a6686a06ba300bab18eh "opt_ie[0] = %02X - element vendor\n"
924f3e72988efae04c4357a6686a06ba300bab18eh "opt_ie[1] = %02X - length\n"
924f3e72988efae04c4357a6686a06ba300bab18eh "opt_ie[2,3,4] = %02X %02X %02X - oui\n"
924f3e72988efae04c4357a6686a06ba300bab18eh "opt_ie[5] = %02X - oui type\n"
924f3e72988efae04c4357a6686a06ba300bab18eh "opt_ie[6,7] = %02X %02X - spec version \n"
924f3e72988efae04c4357a6686a06ba300bab18eh "opt_ie[8,9,10,11] = %02X %02X %02X %02X - gk cipher\n"
924f3e72988efae04c4357a6686a06ba300bab18eh "opt_ie[12,13] = %02X %02X - pairwise key cipher(1)\n"
924f3e72988efae04c4357a6686a06ba300bab18eh "opt_ie[14,15,16,17] = %02X %02X %02X %02X - ciphers\n"
924f3e72988efae04c4357a6686a06ba300bab18eh "opt_ie[18,19] = %02X %02X - authselcont(1) \n"
924f3e72988efae04c4357a6686a06ba300bab18eh "opt_ie[20,21,22,23] = %02X %02X %02X %02X - authsels\n",
924f3e72988efae04c4357a6686a06ba300bab18eh wpa_level[1], wpa_level[0], wpa_level[1],
924f3e72988efae04c4357a6686a06ba300bab18eh wpa_level[2], wpa_level[3], wpa_level[4],
924f3e72988efae04c4357a6686a06ba300bab18eh wpa_level[5], wpa_level[6], wpa_level[7],
924f3e72988efae04c4357a6686a06ba300bab18eh wpa_level[8], wpa_level[9], wpa_level[10],
924f3e72988efae04c4357a6686a06ba300bab18eh wpa_level[11], wpa_level[12], wpa_level[13],
924f3e72988efae04c4357a6686a06ba300bab18eh wpa_level[14], wpa_level[15], wpa_level[16],
924f3e72988efae04c4357a6686a06ba300bab18eh wpa_level[17], wpa_level[18], wpa_level[19],
924f3e72988efae04c4357a6686a06ba300bab18eh wpa_level[20], wpa_level[21], wpa_level[22],
924f3e72988efae04c4357a6686a06ba300bab18eh wpa_level[23]));
924f3e72988efae04c4357a6686a06ba300bab18eh
924f3e72988efae04c4357a6686a06ba300bab18eh err = ipw2200_cmd(sc, IPW2200_CMD_SET_OPTIE,
924f3e72988efae04c4357a6686a06ba300bab18eh ic->ic_opt_ie, ic->ic_opt_ie_len, 1);
924f3e72988efae04c4357a6686a06ba300bab18eh if (err != DDI_SUCCESS)
924f3e72988efae04c4357a6686a06ba300bab18eh return (err);
924f3e72988efae04c4357a6686a06ba300bab18eh }
924f3e72988efae04c4357a6686a06ba300bab18eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * set the sensitive
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh data = LE_32(in->in_rssi);
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_DBG(IPW2200_DBG_WIFI, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2200_auth_and_assoc(): "
bb5e3b2f129cc39517b925419c22f69a378ec023eh "setting sensitivity to rssi:(%u)\n", (uint8_t)in->in_rssi));
bb5e3b2f129cc39517b925419c22f69a378ec023eh err = ipw2200_cmd(sc, IPW2200_CMD_SET_SENSITIVITY,
bb5e3b2f129cc39517b925419c22f69a378ec023eh &data, sizeof (data), 1);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (err != DDI_SUCCESS)
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (err);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
924f3e72988efae04c4357a6686a06ba300bab18eh * set mode and channel for assocation command
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh assoc.mode = IEEE80211_IS_CHAN_5GHZ(in->in_chan) ?
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_MODE_11A : IPW2200_MODE_11G;
bb5e3b2f129cc39517b925419c22f69a378ec023eh assoc.chan = ieee80211_chan2ieee(ic, in->in_chan);
924f3e72988efae04c4357a6686a06ba300bab18eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * use the value set to ic_bss to retraive current sharedmode
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (ic->ic_bss->in_authmode == WL_SHAREDKEY) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh assoc.auth = (ic->ic_def_txkey << 4) | IPW2200_AUTH_SHARED;
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_DBG(IPW2200_DBG_IOCTL, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2200_auth_and_assoc(): "
bb5e3b2f129cc39517b925419c22f69a378ec023eh "associate to shared key mode, set thru. ioctl"));
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
924f3e72988efae04c4357a6686a06ba300bab18eh
924f3e72988efae04c4357a6686a06ba300bab18eh if (ic->ic_flags & IEEE80211_F_WPA)
924f3e72988efae04c4357a6686a06ba300bab18eh assoc.policy = LE_16(IPW2200_POLICY_WPA); /* RSN/WPA active */
bb5e3b2f129cc39517b925419c22f69a378ec023eh (void) memcpy(assoc.tstamp, in->in_tstamp.data, 8);
bb5e3b2f129cc39517b925419c22f69a378ec023eh assoc.capinfo = LE_16(in->in_capinfo);
bb5e3b2f129cc39517b925419c22f69a378ec023eh assoc.lintval = LE_16(ic->ic_lintval);
bb5e3b2f129cc39517b925419c22f69a378ec023eh assoc.intval = LE_16(in->in_intval);
bb5e3b2f129cc39517b925419c22f69a378ec023eh IEEE80211_ADDR_COPY(assoc.bssid, in->in_bssid);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (ic->ic_opmode == IEEE80211_M_IBSS)
bb5e3b2f129cc39517b925419c22f69a378ec023eh IEEE80211_ADDR_COPY(assoc.dst, ipw2200_broadcast_addr);
bb5e3b2f129cc39517b925419c22f69a378ec023eh else
bb5e3b2f129cc39517b925419c22f69a378ec023eh IEEE80211_ADDR_COPY(assoc.dst, in->in_bssid);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_DBG(IPW2200_DBG_WIFI, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2200_auth_and_assoc(): "
bb5e3b2f129cc39517b925419c22f69a378ec023eh "associate to bssid(%2x:%2x:%2x:%2x:%2x:%2x:), "
bb5e3b2f129cc39517b925419c22f69a378ec023eh "chan(%u), auth(%u)\n",
bb5e3b2f129cc39517b925419c22f69a378ec023eh assoc.bssid[0], assoc.bssid[1], assoc.bssid[2],
bb5e3b2f129cc39517b925419c22f69a378ec023eh assoc.bssid[3], assoc.bssid[4], assoc.bssid[5],
bb5e3b2f129cc39517b925419c22f69a378ec023eh assoc.chan, assoc.auth));
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (ipw2200_cmd(sc, IPW2200_CMD_ASSOCIATE,
bb5e3b2f129cc39517b925419c22f69a378ec023eh &assoc, sizeof (assoc), 1));
bb5e3b2f129cc39517b925419c22f69a378ec023eh}
bb5e3b2f129cc39517b925419c22f69a378ec023eh
924f3e72988efae04c4357a6686a06ba300bab18eh/*
924f3e72988efae04c4357a6686a06ba300bab18eh * Send the dis-association command to h/w, will receive notification to claim
924f3e72988efae04c4357a6686a06ba300bab18eh * the connection is dis-associated. So, it's not marked as disassociated this
924f3e72988efae04c4357a6686a06ba300bab18eh * moment.
924f3e72988efae04c4357a6686a06ba300bab18eh */
924f3e72988efae04c4357a6686a06ba300bab18ehstatic int
924f3e72988efae04c4357a6686a06ba300bab18ehipw2200_disassoc(struct ipw2200_softc *sc)
924f3e72988efae04c4357a6686a06ba300bab18eh{
924f3e72988efae04c4357a6686a06ba300bab18eh struct ipw2200_associate assoc;
924f3e72988efae04c4357a6686a06ba300bab18eh assoc.type = 2;
924f3e72988efae04c4357a6686a06ba300bab18eh return (ipw2200_cmd(sc, IPW2200_CMD_ASSOCIATE, &assoc,
924f3e72988efae04c4357a6686a06ba300bab18eh sizeof (assoc), 1));
924f3e72988efae04c4357a6686a06ba300bab18eh}
924f3e72988efae04c4357a6686a06ba300bab18eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh/* ARGSUSED */
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic int
bb5e3b2f129cc39517b925419c22f69a378ec023ehipw2200_newstate(struct ieee80211com *ic, enum ieee80211_state state, int arg)
bb5e3b2f129cc39517b925419c22f69a378ec023eh{
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct ipw2200_softc *sc = (struct ipw2200_softc *)ic;
bb5e3b2f129cc39517b925419c22f69a378ec023eh wifi_data_t wd = { 0 };
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh switch (state) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh case IEEE80211_S_SCAN:
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (!(sc->sc_flags & IPW2200_FLAG_SCANNING)) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh ic->ic_flags |= IEEE80211_F_SCAN | IEEE80211_F_ASCAN;
bb5e3b2f129cc39517b925419c22f69a378ec023eh (void) ipw2200_start_scan(sc);
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh break;
bb5e3b2f129cc39517b925419c22f69a378ec023eh case IEEE80211_S_AUTH:
924f3e72988efae04c4357a6686a06ba300bab18eh /*
924f3e72988efae04c4357a6686a06ba300bab18eh * The firmware will fail if we are already associated
924f3e72988efae04c4357a6686a06ba300bab18eh */
924f3e72988efae04c4357a6686a06ba300bab18eh if (sc->sc_flags & IPW2200_FLAG_ASSOCIATED)
924f3e72988efae04c4357a6686a06ba300bab18eh (void) ipw2200_disassoc(sc);
bb5e3b2f129cc39517b925419c22f69a378ec023eh (void) ipw2200_auth_and_assoc(sc);
bb5e3b2f129cc39517b925419c22f69a378ec023eh break;
bb5e3b2f129cc39517b925419c22f69a378ec023eh case IEEE80211_S_RUN:
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * We can send data now; update the fastpath with our
bb5e3b2f129cc39517b925419c22f69a378ec023eh * current associated BSSID and other relevant settings.
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
924f3e72988efae04c4357a6686a06ba300bab18eh wd.wd_secalloc = ieee80211_crypto_getciphertype(ic);
924f3e72988efae04c4357a6686a06ba300bab18eh 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 break;
bb5e3b2f129cc39517b925419c22f69a378ec023eh case IEEE80211_S_ASSOC:
bb5e3b2f129cc39517b925419c22f69a378ec023eh case IEEE80211_S_INIT:
bb5e3b2f129cc39517b925419c22f69a378ec023eh break;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
924f3e72988efae04c4357a6686a06ba300bab18eh * notify to update the link, and WPA
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh if ((ic->ic_state != IEEE80211_S_RUN) && (state == IEEE80211_S_RUN)) {
924f3e72988efae04c4357a6686a06ba300bab18eh ieee80211_notify_node_join(ic, ic->ic_bss);
bb5e3b2f129cc39517b925419c22f69a378ec023eh } else if ((ic->ic_state == IEEE80211_S_RUN) &&
76939ce0e89c177cb48bf98208fd3d831eb283d5eh (state != IEEE80211_S_RUN)) {
924f3e72988efae04c4357a6686a06ba300bab18eh ieee80211_notify_node_leave(ic, ic->ic_bss);
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_DBG(IPW2200_DBG_WIFI, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2200_newstat(): %s -> %s\n",
bb5e3b2f129cc39517b925419c22f69a378ec023eh ieee80211_state_name[ic->ic_state],
bb5e3b2f129cc39517b925419c22f69a378ec023eh ieee80211_state_name[state]));
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh ic->ic_state = state;
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (DDI_SUCCESS);
bb5e3b2f129cc39517b925419c22f69a378ec023eh}
bb5e3b2f129cc39517b925419c22f69a378ec023eh/*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * GLD operations
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh/* ARGSUSED */
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic int
bb5e3b2f129cc39517b925419c22f69a378ec023ehipw2200_m_stat(void *arg, uint_t stat, uint64_t *val)
bb5e3b2f129cc39517b925419c22f69a378ec023eh{
922d2c76afbee21520ffa2088c4e60dcb80d3945eh ieee80211com_t *ic = (ieee80211com_t *)arg;
922d2c76afbee21520ffa2088c4e60dcb80d3945eh struct ipw2200_softc *sc = (struct ipw2200_softc *)ic;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_DBG(IPW2200_DBG_GLD, (((struct ipw2200_softc *)arg)->sc_dip,
bb5e3b2f129cc39517b925419c22f69a378ec023eh CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2200_m_stat(): enter\n"));
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * Some of below statistic data are from hardware, some from net80211
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh switch (stat) {
922d2c76afbee21520ffa2088c4e60dcb80d3945eh case MAC_STAT_NOXMTBUF:
922d2c76afbee21520ffa2088c4e60dcb80d3945eh *val = ic->ic_stats.is_tx_nobuf;
922d2c76afbee21520ffa2088c4e60dcb80d3945eh break;
922d2c76afbee21520ffa2088c4e60dcb80d3945eh case MAC_STAT_IERRORS:
922d2c76afbee21520ffa2088c4e60dcb80d3945eh *val = sc->sc_stats.sc_rx_len_err;
922d2c76afbee21520ffa2088c4e60dcb80d3945eh break;
922d2c76afbee21520ffa2088c4e60dcb80d3945eh case MAC_STAT_OERRORS:
922d2c76afbee21520ffa2088c4e60dcb80d3945eh *val = sc->sc_stats.sc_tx_discard +
922d2c76afbee21520ffa2088c4e60dcb80d3945eh sc->sc_stats.sc_tx_alloc_fail +
922d2c76afbee21520ffa2088c4e60dcb80d3945eh sc->sc_stats.sc_tx_encap_fail +
922d2c76afbee21520ffa2088c4e60dcb80d3945eh sc->sc_stats.sc_tx_crypto_fail;
922d2c76afbee21520ffa2088c4e60dcb80d3945eh break;
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, retraive 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 /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * Get blow information from net80211
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh case WIFI_STAT_RTS_SUCCESS:
bb5e3b2f129cc39517b925419c22f69a378ec023eh case WIFI_STAT_RTS_FAILURE:
bb5e3b2f129cc39517b925419c22f69a378ec023eh case WIFI_STAT_ACK_FAILURE:
bb5e3b2f129cc39517b925419c22f69a378ec023eh case WIFI_STAT_RX_FRAGS:
bb5e3b2f129cc39517b925419c22f69a378ec023eh case WIFI_STAT_MCAST_RX:
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 later
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh case MAC_STAT_IFSPEED:
bb5e3b2f129cc39517b925419c22f69a378ec023eh default:
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (ENOTSUP);
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (0);
bb5e3b2f129cc39517b925419c22f69a378ec023eh}
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh/* ARGSUSED */
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic int
bb5e3b2f129cc39517b925419c22f69a378ec023ehipw2200_m_multicst(void *arg, boolean_t add, const uint8_t *mca)
bb5e3b2f129cc39517b925419c22f69a378ec023eh{
bb5e3b2f129cc39517b925419c22f69a378ec023eh /* not supported */
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_DBG(IPW2200_DBG_GLD, (((struct ipw2200_softc *)arg)->sc_dip,
bb5e3b2f129cc39517b925419c22f69a378ec023eh CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2200_m_multicst(): enter\n"));
bb5e3b2f129cc39517b925419c22f69a378ec023eh
922d2c76afbee21520ffa2088c4e60dcb80d3945eh return (0);
bb5e3b2f129cc39517b925419c22f69a378ec023eh}
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh/*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * Multithread handler for linkstatus, fatal error recovery, get statistic
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic void
bb5e3b2f129cc39517b925419c22f69a378ec023ehipw2200_thread(struct ipw2200_softc *sc)
bb5e3b2f129cc39517b925419c22f69a378ec023eh{
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct ieee80211com *ic = &sc->sc_ic;
982d85fc28969b583003622c0bd41d9db0ccecd7eh enum ieee80211_state ostate;
bb5e3b2f129cc39517b925419c22f69a378ec023eh int32_t nlstate;
bb5e3b2f129cc39517b925419c22f69a378ec023eh int stat_cnt = 0;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_DBG(IPW2200_DBG_SOFTINT, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2200_thread(): enter, linkstate %d\n", sc->sc_linkstate));
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh mutex_enter(&sc->sc_mflock);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh while (sc->sc_mfthread_switch) {
922d2c76afbee21520ffa2088c4e60dcb80d3945eh /*
922d2c76afbee21520ffa2088c4e60dcb80d3945eh * when radio is off or SUSPEND status, nothing to do
922d2c76afbee21520ffa2088c4e60dcb80d3945eh */
922d2c76afbee21520ffa2088c4e60dcb80d3945eh if ((ipw2200_radio_status(sc) == 0) ||
922d2c76afbee21520ffa2088c4e60dcb80d3945eh sc->sc_flags & IPW2200_FLAG_SUSPEND) {
922d2c76afbee21520ffa2088c4e60dcb80d3945eh goto wait_loop;
922d2c76afbee21520ffa2088c4e60dcb80d3945eh }
922d2c76afbee21520ffa2088c4e60dcb80d3945eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * notify the link state
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (ic->ic_mach && (sc->sc_flags & IPW2200_FLAG_LINK_CHANGE)) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_DBG(IPW2200_DBG_SOFTINT, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2200_thread(): link status --> %d\n",
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_linkstate));
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_flags &= ~IPW2200_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 fatal error
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (ic->ic_mach &&
bb5e3b2f129cc39517b925419c22f69a378ec023eh (sc->sc_flags & IPW2200_FLAG_HW_ERR_RECOVER)) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_DBG(IPW2200_DBG_FATAL, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2200_thread(): "
bb5e3b2f129cc39517b925419c22f69a378ec023eh "try to recover fatal hw error\n"));
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_flags &= ~IPW2200_FLAG_HW_ERR_RECOVER;
bb5e3b2f129cc39517b925419c22f69a378ec023eh mutex_exit(&sc->sc_mflock);
982d85fc28969b583003622c0bd41d9db0ccecd7eh
924f3e72988efae04c4357a6686a06ba300bab18eh /* stop again */
982d85fc28969b583003622c0bd41d9db0ccecd7eh ostate = ic->ic_state;
bb5e3b2f129cc39517b925419c22f69a378ec023eh (void) ipw2200_init(sc); /* Force state machine */
924f3e72988efae04c4357a6686a06ba300bab18eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * workround. Delay for a while after init especially
bb5e3b2f129cc39517b925419c22f69a378ec023eh * when something wrong happened already.
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh delay(drv_usectohz(delay_fatal_recover));
982d85fc28969b583003622c0bd41d9db0ccecd7eh
982d85fc28969b583003622c0bd41d9db0ccecd7eh /*
982d85fc28969b583003622c0bd41d9db0ccecd7eh * Init scan will recovery the original connection if
982d85fc28969b583003622c0bd41d9db0ccecd7eh * the original state is run
982d85fc28969b583003622c0bd41d9db0ccecd7eh */
982d85fc28969b583003622c0bd41d9db0ccecd7eh if (ostate != IEEE80211_S_INIT)
982d85fc28969b583003622c0bd41d9db0ccecd7eh ieee80211_begin_scan(ic, 0);
982d85fc28969b583003622c0bd41d9db0ccecd7eh
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
bb5e3b2f129cc39517b925419c22f69a378ec023eh stat_cnt = 0; /* re-start */
bb5e3b2f129cc39517b925419c22f69a378ec023eh mutex_exit(&sc->sc_mflock);
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2200_get_statistics(sc);
bb5e3b2f129cc39517b925419c22f69a378ec023eh mutex_enter(&sc->sc_mflock);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh } else
bb5e3b2f129cc39517b925419c22f69a378ec023eh stat_cnt++; /* until 1s */
bb5e3b2f129cc39517b925419c22f69a378ec023eh
922d2c76afbee21520ffa2088c4e60dcb80d3945ehwait_loop:
bb5e3b2f129cc39517b925419c22f69a378ec023eh mutex_exit(&sc->sc_mflock);
bb5e3b2f129cc39517b925419c22f69a378ec023eh delay(drv_usectohz(delay_aux_thread));
bb5e3b2f129cc39517b925419c22f69a378ec023eh mutex_enter(&sc->sc_mflock);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_mf_thread = NULL;
bb5e3b2f129cc39517b925419c22f69a378ec023eh cv_signal(&sc->sc_mfthread_cv);
bb5e3b2f129cc39517b925419c22f69a378ec023eh mutex_exit(&sc->sc_mflock);
bb5e3b2f129cc39517b925419c22f69a378ec023eh}
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic int
bb5e3b2f129cc39517b925419c22f69a378ec023ehipw2200_m_start(void *arg)
bb5e3b2f129cc39517b925419c22f69a378ec023eh{
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct ipw2200_softc *sc = (struct ipw2200_softc *)arg;
982d85fc28969b583003622c0bd41d9db0ccecd7eh struct ieee80211com *ic = &sc->sc_ic;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_DBG(IPW2200_DBG_GLD, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2200_m_start(): enter\n"));
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * initialize ipw2200 hardware, everything ok will start scan
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh (void) ipw2200_init(sc);
924f3e72988efae04c4357a6686a06ba300bab18eh
982d85fc28969b583003622c0bd41d9db0ccecd7eh /*
982d85fc28969b583003622c0bd41d9db0ccecd7eh * set the state machine to INIT
982d85fc28969b583003622c0bd41d9db0ccecd7eh */
982d85fc28969b583003622c0bd41d9db0ccecd7eh ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_flags |= IPW2200_FLAG_RUNNING;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
924f3e72988efae04c4357a6686a06ba300bab18eh /*
924f3e72988efae04c4357a6686a06ba300bab18eh * fix KCF bug. - workaround, need to fix it in net80211
924f3e72988efae04c4357a6686a06ba300bab18eh */
924f3e72988efae04c4357a6686a06ba300bab18eh (void) crypto_mech2id(SUN_CKM_RC4);
924f3e72988efae04c4357a6686a06ba300bab18eh
922d2c76afbee21520ffa2088c4e60dcb80d3945eh return (0);
bb5e3b2f129cc39517b925419c22f69a378ec023eh}
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic void
bb5e3b2f129cc39517b925419c22f69a378ec023ehipw2200_m_stop(void *arg)
bb5e3b2f129cc39517b925419c22f69a378ec023eh{
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct ipw2200_softc *sc = (struct ipw2200_softc *)arg;
982d85fc28969b583003622c0bd41d9db0ccecd7eh struct ieee80211com *ic = &sc->sc_ic;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_DBG(IPW2200_DBG_GLD, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2200_m_stop(): enter\n"));
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2200_stop(sc);
982d85fc28969b583003622c0bd41d9db0ccecd7eh /*
982d85fc28969b583003622c0bd41d9db0ccecd7eh * set the state machine to INIT
982d85fc28969b583003622c0bd41d9db0ccecd7eh */
982d85fc28969b583003622c0bd41d9db0ccecd7eh ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_flags &= ~IPW2200_FLAG_RUNNING;
bb5e3b2f129cc39517b925419c22f69a378ec023eh}
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic int
bb5e3b2f129cc39517b925419c22f69a378ec023ehipw2200_m_unicst(void *arg, const uint8_t *macaddr)
bb5e3b2f129cc39517b925419c22f69a378ec023eh{
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct ipw2200_softc *sc = (struct ipw2200_softc *)arg;
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct ieee80211com *ic = &sc->sc_ic;
bb5e3b2f129cc39517b925419c22f69a378ec023eh int err;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_DBG(IPW2200_DBG_GLD, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2200_m_unicst(): enter\n"));
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_DBG(IPW2200_DBG_GLD, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2200_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
bb5e3b2f129cc39517b925419c22f69a378ec023eh IEEE80211_ADDR_COPY(ic->ic_macaddr, macaddr);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (sc->sc_flags & IPW2200_FLAG_RUNNING) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh err = ipw2200_config(sc);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (err != DDI_SUCCESS) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_WARN((sc->sc_dip, CE_WARN,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2200_m_unicst(): "
bb5e3b2f129cc39517b925419c22f69a378ec023eh "device configuration failed\n"));
bb5e3b2f129cc39517b925419c22f69a378ec023eh goto fail;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
922d2c76afbee21520ffa2088c4e60dcb80d3945eh return (0);
bb5e3b2f129cc39517b925419c22f69a378ec023ehfail:
922d2c76afbee21520ffa2088c4e60dcb80d3945eh return (EIO);
bb5e3b2f129cc39517b925419c22f69a378ec023eh}
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic int
bb5e3b2f129cc39517b925419c22f69a378ec023ehipw2200_m_promisc(void *arg, boolean_t on)
bb5e3b2f129cc39517b925419c22f69a378ec023eh{
bb5e3b2f129cc39517b925419c22f69a378ec023eh /* not supported */
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct ipw2200_softc *sc = (struct ipw2200_softc *)arg;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_DBG(IPW2200_DBG_GLD, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2200_m_promisc(): enter. "
bb5e3b2f129cc39517b925419c22f69a378ec023eh "GLD setting promiscuous mode - %d\n", on));
bb5e3b2f129cc39517b925419c22f69a378ec023eh
922d2c76afbee21520ffa2088c4e60dcb80d3945eh return (0);
bb5e3b2f129cc39517b925419c22f69a378ec023eh}
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic mblk_t *
bb5e3b2f129cc39517b925419c22f69a378ec023ehipw2200_m_tx(void *arg, mblk_t *mp)
bb5e3b2f129cc39517b925419c22f69a378ec023eh{
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct ipw2200_softc *sc = (struct ipw2200_softc *)arg;
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct ieee80211com *ic = &sc->sc_ic;
bb5e3b2f129cc39517b925419c22f69a378ec023eh mblk_t *next;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
922d2c76afbee21520ffa2088c4e60dcb80d3945eh /*
922d2c76afbee21520ffa2088c4e60dcb80d3945eh * when driver in on suspend state, freemsgchain directly
922d2c76afbee21520ffa2088c4e60dcb80d3945eh */
922d2c76afbee21520ffa2088c4e60dcb80d3945eh if (sc->sc_flags & IPW2200_FLAG_SUSPEND) {
922d2c76afbee21520ffa2088c4e60dcb80d3945eh IPW2200_DBG(IPW2200_DBG_SUSPEND, (sc->sc_dip, CE_CONT,
922d2c76afbee21520ffa2088c4e60dcb80d3945eh "ipw2200_m_tx(): suspend status, discard msg\n"));
922d2c76afbee21520ffa2088c4e60dcb80d3945eh sc->sc_stats.sc_tx_discard++; /* discard data */
922d2c76afbee21520ffa2088c4e60dcb80d3945eh freemsgchain(mp);
922d2c76afbee21520ffa2088c4e60dcb80d3945eh return (NULL);
922d2c76afbee21520ffa2088c4e60dcb80d3945eh }
922d2c76afbee21520ffa2088c4e60dcb80d3945eh
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 IPW2200_DBG(IPW2200_DBG_GLD, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2200_m_tx(): discard msg, ic_state = %u\n",
bb5e3b2f129cc39517b925419c22f69a378ec023eh ic->ic_state));
922d2c76afbee21520ffa2088c4e60dcb80d3945eh sc->sc_stats.sc_tx_discard++; /* discard data */
bb5e3b2f129cc39517b925419c22f69a378ec023eh freemsgchain(mp);
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (NULL);
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh while (mp != NULL) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh next = mp->b_next;
bb5e3b2f129cc39517b925419c22f69a378ec023eh mp->b_next = NULL;
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (ipw2200_send(ic, mp, IEEE80211_FC0_TYPE_DATA) ==
924f3e72988efae04c4357a6686a06ba300bab18eh ENOMEM) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh mp->b_next = next;
bb5e3b2f129cc39517b925419c22f69a378ec023eh break;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh mp = next;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (mp);
bb5e3b2f129cc39517b925419c22f69a378ec023eh}
bb5e3b2f129cc39517b925419c22f69a378ec023eh
924f3e72988efae04c4357a6686a06ba300bab18eh/*
924f3e72988efae04c4357a6686a06ba300bab18eh * ipw2200_send(): send data. softway to handle crypto_encap.
924f3e72988efae04c4357a6686a06ba300bab18eh */
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic int
bb5e3b2f129cc39517b925419c22f69a378ec023ehipw2200_send(ieee80211com_t *ic, mblk_t *mp, uint8_t type)
bb5e3b2f129cc39517b925419c22f69a378ec023eh{
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct ipw2200_softc *sc = (struct ipw2200_softc *)ic;
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct ieee80211_node *in;
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct ieee80211_frame *wh;
924f3e72988efae04c4357a6686a06ba300bab18eh struct ieee80211_key *k;
924f3e72988efae04c4357a6686a06ba300bab18eh mblk_t *m0, *m;
bb5e3b2f129cc39517b925419c22f69a378ec023eh size_t cnt, off;
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct ipw2200_tx_desc *txdsc;
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct dma_region *dr;
bb5e3b2f129cc39517b925419c22f69a378ec023eh uint32_t idx;
924f3e72988efae04c4357a6686a06ba300bab18eh int err = DDI_SUCCESS;
bb5e3b2f129cc39517b925419c22f69a378ec023eh /* tmp pointer, used to pack header and payload */
bb5e3b2f129cc39517b925419c22f69a378ec023eh uint8_t *p;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh ASSERT(mp->b_next == NULL);
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_DBG(IPW2200_DBG_GLD, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2200_send(): enter\n"));
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh if ((type & IEEE80211_FC0_TYPE_MASK) != IEEE80211_FC0_TYPE_DATA) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * skip all management frames since ipw2200 won't generate any
bb5e3b2f129cc39517b925419c22f69a378ec023eh * management frames. Therefore, drop this package.
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh freemsg(mp);
924f3e72988efae04c4357a6686a06ba300bab18eh err = DDI_FAILURE;
bb5e3b2f129cc39517b925419c22f69a378ec023eh goto fail0;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh mutex_enter(&sc->sc_tx_lock);
922d2c76afbee21520ffa2088c4e60dcb80d3945eh if (sc->sc_flags & IPW2200_FLAG_SUSPEND) {
922d2c76afbee21520ffa2088c4e60dcb80d3945eh /*
922d2c76afbee21520ffa2088c4e60dcb80d3945eh * when sending data, system runs into suspend status,
922d2c76afbee21520ffa2088c4e60dcb80d3945eh * return fail directly
922d2c76afbee21520ffa2088c4e60dcb80d3945eh */
922d2c76afbee21520ffa2088c4e60dcb80d3945eh err = ENXIO;
922d2c76afbee21520ffa2088c4e60dcb80d3945eh goto fail0;
922d2c76afbee21520ffa2088c4e60dcb80d3945eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * need 1 empty descriptor
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (sc->sc_tx_free <= IPW2200_TX_RING_MIN) {
924f3e72988efae04c4357a6686a06ba300bab18eh mutex_enter(&sc->sc_resched_lock);
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_DBG(IPW2200_DBG_RING, (sc->sc_dip, CE_WARN,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2200_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 |= IPW2200_FLAG_TX_SCHED;
924f3e72988efae04c4357a6686a06ba300bab18eh err = ENOMEM;
924f3e72988efae04c4357a6686a06ba300bab18eh mutex_exit(&sc->sc_resched_lock);
bb5e3b2f129cc39517b925419c22f69a378ec023eh goto fail1;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_DBG(IPW2200_DBG_RING, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2200_send(): tx-free=%d,tx-curr=%d\n",
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_tx_free, sc->sc_tx_cur));
bb5e3b2f129cc39517b925419c22f69a378ec023eh
924f3e72988efae04c4357a6686a06ba300bab18eh /*
924f3e72988efae04c4357a6686a06ba300bab18eh * put the mp into one blk, and use it to do the crypto_encap
924f3e72988efae04c4357a6686a06ba300bab18eh * if necessaary.
924f3e72988efae04c4357a6686a06ba300bab18eh */
924f3e72988efae04c4357a6686a06ba300bab18eh m = allocb(msgdsize(mp) + 32, BPRI_MED);
924f3e72988efae04c4357a6686a06ba300bab18eh if (m == NULL) { /* can not alloc buf, drop this package */
924f3e72988efae04c4357a6686a06ba300bab18eh IPW2200_DBG(IPW2200_DBG_WIFI, (sc->sc_dip, CE_CONT,
924f3e72988efae04c4357a6686a06ba300bab18eh "ipw2200_send(): msg allocation failed\n"));
924f3e72988efae04c4357a6686a06ba300bab18eh freemsg(mp);
922d2c76afbee21520ffa2088c4e60dcb80d3945eh sc->sc_stats.sc_tx_alloc_fail++; /* alloc fail */
922d2c76afbee21520ffa2088c4e60dcb80d3945eh ic->ic_stats.is_tx_failed++; /* trans failed */
924f3e72988efae04c4357a6686a06ba300bab18eh err = DDI_FAILURE;
924f3e72988efae04c4357a6686a06ba300bab18eh goto fail1;
924f3e72988efae04c4357a6686a06ba300bab18eh }
924f3e72988efae04c4357a6686a06ba300bab18eh for (off = 0, m0 = mp; m0 != NULL; m0 = m0->b_cont) {
924f3e72988efae04c4357a6686a06ba300bab18eh cnt = MBLKL(m0);
924f3e72988efae04c4357a6686a06ba300bab18eh (void) memcpy(m->b_rptr + off, m0->b_rptr, cnt);
924f3e72988efae04c4357a6686a06ba300bab18eh off += cnt;
924f3e72988efae04c4357a6686a06ba300bab18eh }
924f3e72988efae04c4357a6686a06ba300bab18eh m->b_wptr += off;
924f3e72988efae04c4357a6686a06ba300bab18eh
924f3e72988efae04c4357a6686a06ba300bab18eh /*
924f3e72988efae04c4357a6686a06ba300bab18eh * find tx_node, and encapsulate the data
924f3e72988efae04c4357a6686a06ba300bab18eh */
924f3e72988efae04c4357a6686a06ba300bab18eh wh = (struct ieee80211_frame *)m->b_rptr;
bb5e3b2f129cc39517b925419c22f69a378ec023eh in = ieee80211_find_txnode(ic, wh->i_addr1);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (in == NULL) { /* can not find the tx node, drop the package */
922d2c76afbee21520ffa2088c4e60dcb80d3945eh sc->sc_stats.sc_tx_encap_fail++; /* tx encap fail */
922d2c76afbee21520ffa2088c4e60dcb80d3945eh ic->ic_stats.is_tx_failed++; /* trans failed */
bb5e3b2f129cc39517b925419c22f69a378ec023eh freemsg(mp);
924f3e72988efae04c4357a6686a06ba300bab18eh err = DDI_FAILURE;
924f3e72988efae04c4357a6686a06ba300bab18eh goto fail2;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh in->in_inact = 0;
924f3e72988efae04c4357a6686a06ba300bab18eh
924f3e72988efae04c4357a6686a06ba300bab18eh (void) ieee80211_encap(ic, m, in);
bb5e3b2f129cc39517b925419c22f69a378ec023eh ieee80211_free_node(in);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
924f3e72988efae04c4357a6686a06ba300bab18eh if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
924f3e72988efae04c4357a6686a06ba300bab18eh k = ieee80211_crypto_encap(ic, m);
924f3e72988efae04c4357a6686a06ba300bab18eh if (k == NULL) { /* can not get the key, drop packages */
924f3e72988efae04c4357a6686a06ba300bab18eh IPW2200_DBG(IPW2200_DBG_WIFI, (sc->sc_dip, CE_CONT,
924f3e72988efae04c4357a6686a06ba300bab18eh "ipw2200_send(): "
924f3e72988efae04c4357a6686a06ba300bab18eh "Encrypting 802.11 frame failed\n"));
922d2c76afbee21520ffa2088c4e60dcb80d3945eh sc->sc_stats.sc_tx_crypto_fail++; /* tx encap fail */
922d2c76afbee21520ffa2088c4e60dcb80d3945eh ic->ic_stats.is_tx_failed++; /* trans failed */
924f3e72988efae04c4357a6686a06ba300bab18eh freemsg(mp);
924f3e72988efae04c4357a6686a06ba300bab18eh err = DDI_FAILURE;
924f3e72988efae04c4357a6686a06ba300bab18eh goto fail2;
924f3e72988efae04c4357a6686a06ba300bab18eh }
924f3e72988efae04c4357a6686a06ba300bab18eh wh = (struct ieee80211_frame *)m->b_rptr;
924f3e72988efae04c4357a6686a06ba300bab18eh }
924f3e72988efae04c4357a6686a06ba300bab18eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
924f3e72988efae04c4357a6686a06ba300bab18eh * get txdsc
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh idx = sc->sc_tx_cur;
bb5e3b2f129cc39517b925419c22f69a378ec023eh txdsc = &sc->sc_txdsc[idx];
bb5e3b2f129cc39517b925419c22f69a378ec023eh (void) memset(txdsc, 0, sizeof (*txdsc));
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * extract header from message
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh p = (uint8_t *)&txdsc->wh;
924f3e72988efae04c4357a6686a06ba300bab18eh off = sizeof (struct ieee80211_frame);
924f3e72988efae04c4357a6686a06ba300bab18eh (void) memcpy(p, m->b_rptr, off);
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * extract payload from message
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh dr = &sc->sc_dma_txbufs[idx];
bb5e3b2f129cc39517b925419c22f69a378ec023eh p = sc->sc_txbufs[idx];
924f3e72988efae04c4357a6686a06ba300bab18eh cnt = MBLKL(m);
924f3e72988efae04c4357a6686a06ba300bab18eh (void) memcpy(p, m->b_rptr + off, cnt - off);
924f3e72988efae04c4357a6686a06ba300bab18eh cnt -= off;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh txdsc->hdr.type = IPW2200_HDR_TYPE_DATA;
bb5e3b2f129cc39517b925419c22f69a378ec023eh txdsc->hdr.flags = IPW2200_HDR_FLAG_IRQ;
bb5e3b2f129cc39517b925419c22f69a378ec023eh txdsc->cmd = IPW2200_DATA_CMD_TX;
924f3e72988efae04c4357a6686a06ba300bab18eh txdsc->len = LE_16(cnt);
bb5e3b2f129cc39517b925419c22f69a378ec023eh txdsc->flags = 0;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (ic->ic_opmode == IEEE80211_M_IBSS) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (!IEEE80211_IS_MULTICAST(wh->i_addr1))
bb5e3b2f129cc39517b925419c22f69a378ec023eh txdsc->flags |= IPW2200_DATA_FLAG_NEED_ACK;
bb5e3b2f129cc39517b925419c22f69a378ec023eh } else if (!IEEE80211_IS_MULTICAST(wh->i_addr3))
bb5e3b2f129cc39517b925419c22f69a378ec023eh txdsc->flags |= IPW2200_DATA_FLAG_NEED_ACK;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
924f3e72988efae04c4357a6686a06ba300bab18eh /* always set it to none wep, because it's handled by software */
924f3e72988efae04c4357a6686a06ba300bab18eh txdsc->flags |= IPW2200_DATA_FLAG_NO_WEP;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (ic->ic_flags & IEEE80211_F_SHPREAMBLE)
bb5e3b2f129cc39517b925419c22f69a378ec023eh txdsc->flags |= IPW2200_DATA_FLAG_SHPREAMBLE;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh txdsc->nseg = LE_32(1);
bb5e3b2f129cc39517b925419c22f69a378ec023eh txdsc->seg_addr[0] = LE_32(dr->dr_pbase);
924f3e72988efae04c4357a6686a06ba300bab18eh txdsc->seg_len[0] = LE_32(cnt);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * DMA sync: buffer and desc
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh (void) ddi_dma_sync(dr->dr_hnd, 0,
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_TXBUF_SIZE, DDI_DMA_SYNC_FORDEV);
bb5e3b2f129cc39517b925419c22f69a378ec023eh (void) ddi_dma_sync(sc->sc_dma_txdsc.dr_hnd,
bb5e3b2f129cc39517b925419c22f69a378ec023eh idx * sizeof (struct ipw2200_tx_desc),
bb5e3b2f129cc39517b925419c22f69a378ec023eh sizeof (struct ipw2200_tx_desc), DDI_DMA_SYNC_FORDEV);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_tx_cur = RING_FORWARD(sc->sc_tx_cur, 1, IPW2200_TX_RING_SIZE);
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_tx_free--;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * update txcur
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2200_csr_put32(sc, IPW2200_CSR_TX1_WRITE_INDEX, sc->sc_tx_cur);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * success, free the original message
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (mp)
bb5e3b2f129cc39517b925419c22f69a378ec023eh freemsg(mp);
924f3e72988efae04c4357a6686a06ba300bab18ehfail2:
924f3e72988efae04c4357a6686a06ba300bab18eh if (m)
924f3e72988efae04c4357a6686a06ba300bab18eh freemsg(m);
bb5e3b2f129cc39517b925419c22f69a378ec023ehfail1:
bb5e3b2f129cc39517b925419c22f69a378ec023eh mutex_exit(&sc->sc_tx_lock);
bb5e3b2f129cc39517b925419c22f69a378ec023ehfail0:
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_DBG(IPW2200_DBG_GLD, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2200_send(): exit - err=%d\n", err));
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (err);
bb5e3b2f129cc39517b925419c22f69a378ec023eh}
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh/*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * IOCTL handlers
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh#define IEEE80211_IOCTL_REQUIRED (1)
bb5e3b2f129cc39517b925419c22f69a378ec023eh#define IEEE80211_IOCTL_NOT_REQUIRED (0)
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic void
bb5e3b2f129cc39517b925419c22f69a378ec023ehipw2200_m_ioctl(void *arg, queue_t *q, mblk_t *m)
bb5e3b2f129cc39517b925419c22f69a378ec023eh{
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct ipw2200_softc *sc = (struct ipw2200_softc *)arg;
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct ieee80211com *ic = &sc->sc_ic;
bb5e3b2f129cc39517b925419c22f69a378ec023eh uint32_t err;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_DBG(IPW2200_DBG_GLD, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2200_m_ioctl(): enter\n"));
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * Check whether or not need to handle this in net80211
bb5e3b2f129cc39517b925419c22f69a378ec023eh *
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (ipw2200_ioctl(sc, q, m) == IEEE80211_IOCTL_NOT_REQUIRED)
bb5e3b2f129cc39517b925419c22f69a378ec023eh return;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh err = ieee80211_ioctl(ic, q, m);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (err == ENETRESET) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (sc->sc_flags & IPW2200_FLAG_RUNNING) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh (void) ipw2200_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 & IPW2200_FLAG_RUNNING)
bb5e3b2f129cc39517b925419c22f69a378ec023eh (void) ipw2200_chip_reset(sc);
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh}
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic int
bb5e3b2f129cc39517b925419c22f69a378ec023ehipw2200_ioctl(struct ipw2200_softc *sc, queue_t *q, mblk_t *m)
bb5e3b2f129cc39517b925419c22f69a378ec023eh{
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct iocblk *iocp;
922d2c76afbee21520ffa2088c4e60dcb80d3945eh uint32_t len, ret, cmd, mblen;
bb5e3b2f129cc39517b925419c22f69a378ec023eh mblk_t *m0;
bb5e3b2f129cc39517b925419c22f69a378ec023eh boolean_t need_privilege;
bb5e3b2f129cc39517b925419c22f69a378ec023eh boolean_t need_net80211;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
922d2c76afbee21520ffa2088c4e60dcb80d3945eh mblen = MBLKL(m);
922d2c76afbee21520ffa2088c4e60dcb80d3945eh if (mblen < sizeof (struct iocblk)) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_DBG(IPW2200_DBG_IOCTL, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2200_ioctl(): ioctl buffer too short, %u\n",
922d2c76afbee21520ffa2088c4e60dcb80d3945eh mblen));
bb5e3b2f129cc39517b925419c22f69a378ec023eh miocnak(q, m, 0, EINVAL);
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * Buf not enough, do not need net80211 either
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
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 IPW2200_DBG(IPW2200_DBG_IOCTL, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2200_ioctl(): unknown cmd 0x%x", cmd));
bb5e3b2f129cc39517b925419c22f69a378ec023eh miocnak(q, m, 0, EINVAL);
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * Unknown cmd, do not need net80211 either
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
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);
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
eae72b5b807baa9116e64502cbb278edf15f3146Sebastien Roy * privilege check fail, do not need net80211 either
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
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 /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * invalid format, do not need net80211 either
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
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 = ipw2200_getset(sc, m0, cmd, &need_net80211);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (!need_net80211) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh len = msgdsize(m0);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_DBG(IPW2200_DBG_IOCTL, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2200_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 - need net80211 handle
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (IEEE80211_IOCTL_REQUIRED);
bb5e3b2f129cc39517b925419c22f69a378ec023eh}
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic int
bb5e3b2f129cc39517b925419c22f69a378ec023ehipw2200_getset(struct ipw2200_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;
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 IPW2200_DBG(IPW2200_DBG_IOCTL, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2200_getset(): id = 0x%x\n", id));
bb5e3b2f129cc39517b925419c22f69a378ec023eh switch (id) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh case WL_RADIO: /* which is not supported by net80211 */
bb5e3b2f129cc39517b925419c22f69a378ec023eh ret = iwi_wificfg_radio(sc, cmd, outfp);
bb5e3b2f129cc39517b925419c22f69a378ec023eh break;
bb5e3b2f129cc39517b925419c22f69a378ec023eh case WL_DESIRED_RATES: /* hardware doesn't support fix-rates */
bb5e3b2f129cc39517b925419c22f69a378ec023eh ret = iwi_wificfg_desrates(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 * case WL_DISASSOCIATE:
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 ((ipw2200_radio_status(sc) == 0) &&
9e2cd38c103ae52a41b09823a11c9b5c059555f0eh (id != WL_LINKSTATUS)) {
9e2cd38c103ae52a41b09823a11c9b5c059555f0eh
9e2cd38c103ae52a41b09823a11c9b5c059555f0eh IPW2200_REPORT((sc->sc_dip, CE_CONT,
9e2cd38c103ae52a41b09823a11c9b5c059555f0eh "iwi: 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 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 Chinaipw2200_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 ipw2200_softc *sc = (struct ipw2200_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 IPW2200_DBG(IPW2200_DBG_BRUSSELS, (sc->sc_dip, CE_CONT,
7efa17f5f4c3cc113e1b0a1e86f43d4bf2ede8fafei feng - Sun Microsystems - Beijing China "ipw2200_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 = ipw2200_radio_status(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 Iyeripw2200_m_propinfo(void *arg, const char *pr_name,
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer mac_prop_id_t wlpd_pr_num, mac_prop_info_handle_t mph)
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer{
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer struct ipw2200_softc *sc = (struct ipw2200_softc *)arg;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer struct ieee80211com *ic = &sc->sc_ic;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer ieee80211_propinfo(ic, pr_name, wlpd_pr_num, mph);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer}
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
7efa17f5f4c3cc113e1b0a1e86f43d4bf2ede8fafei feng - Sun Microsystems - Beijing Chinastatic int
7efa17f5f4c3cc113e1b0a1e86f43d4bf2ede8fafei feng - Sun Microsystems - Beijing Chinaipw2200_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 ipw2200_softc *sc = (struct ipw2200_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 IPW2200_DBG(IPW2200_DBG_BRUSSELS, (sc->sc_dip, CE_CONT,
7efa17f5f4c3cc113e1b0a1e86f43d4bf2ede8fafei feng - Sun Microsystems - Beijing China "ipw2200_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 IPW2200_DBG(IPW2200_DBG_BRUSSELS, (sc->sc_dip, CE_CONT,
7efa17f5f4c3cc113e1b0a1e86f43d4bf2ede8fafei feng - Sun Microsystems - Beijing China "ipw2200_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 & IPW2200_FLAG_RUNNING) {
7efa17f5f4c3cc113e1b0a1e86f43d4bf2ede8fafei feng - Sun Microsystems - Beijing China (void) ipw2200_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 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
bb5e3b2f129cc39517b925419c22f69a378ec023ehiwi_wificfg_radio(struct ipw2200_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) =
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2200_radio_status(sc);
bb5e3b2f129cc39517b925419c22f69a378ec023eh outfp->wldp_length = WIFI_BUF_OFFSET + sizeof (wl_linkstatus_t);
bb5e3b2f129cc39517b925419c22f69a378ec023eh outfp->wldp_result = WL_SUCCESS;
bb5e3b2f129cc39517b925419c22f69a378ec023eh ret = 0; /* command success */
bb5e3b2f129cc39517b925419c22f69a378ec023eh break;
bb5e3b2f129cc39517b925419c22f69a378ec023eh case WLAN_SET_PARAM:
bb5e3b2f129cc39517b925419c22f69a378ec023eh default:
bb5e3b2f129cc39517b925419c22f69a378ec023eh break;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (ret);
bb5e3b2f129cc39517b925419c22f69a378ec023eh}
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic int
bb5e3b2f129cc39517b925419c22f69a378ec023ehiwi_wificfg_desrates(wldp_t *outfp)
bb5e3b2f129cc39517b925419c22f69a378ec023eh{
bb5e3b2f129cc39517b925419c22f69a378ec023eh /* return success, but with result NOTSUPPORTED */
bb5e3b2f129cc39517b925419c22f69a378ec023eh outfp->wldp_length = WIFI_BUF_OFFSET;
bb5e3b2f129cc39517b925419c22f69a378ec023eh outfp->wldp_result = WL_NOTSUPPORTED;
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (0);
bb5e3b2f129cc39517b925419c22f69a378ec023eh}
bb5e3b2f129cc39517b925419c22f69a378ec023eh/* End of IOCTL Handlers */
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023ehvoid
bb5e3b2f129cc39517b925419c22f69a378ec023ehipw2200_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
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (frm[2] <= IEEE80211_CHAN_MAX)
bb5e3b2f129cc39517b925419c22f69a378ec023eh#endif
bb5e3b2f129cc39517b925419c22f69a378ec023eh ic->ic_curchan = &ic->ic_sup_channels[frm[2]];
bb5e3b2f129cc39517b925419c22f69a378ec023eh frm += frm[1] + 2;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh}
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic void
bb5e3b2f129cc39517b925419c22f69a378ec023ehipw2200_rcv_frame(struct ipw2200_softc *sc, struct ipw2200_frame *frame)
bb5e3b2f129cc39517b925419c22f69a378ec023eh{
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct ieee80211com *ic = &sc->sc_ic;
bb5e3b2f129cc39517b925419c22f69a378ec023eh uint8_t *data = (uint8_t *)frame;
bb5e3b2f129cc39517b925419c22f69a378ec023eh uint32_t len;
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct ieee80211_frame *wh;
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct ieee80211_node *in;
bb5e3b2f129cc39517b925419c22f69a378ec023eh mblk_t *m;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh len = LE_16(frame->len);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if ((len < sizeof (struct ieee80211_frame_min)) ||
bb5e3b2f129cc39517b925419c22f69a378ec023eh (len > IPW2200_RXBUF_SIZE)) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_DBG(IPW2200_DBG_RX, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2200_rcv_frame(): bad frame length=%u\n",
bb5e3b2f129cc39517b925419c22f69a378ec023eh LE_16(frame->len)));
922d2c76afbee21520ffa2088c4e60dcb80d3945eh sc->sc_stats.sc_rx_len_err++; /* length doesn't work */
bb5e3b2f129cc39517b925419c22f69a378ec023eh return;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_DBG(IPW2200_DBG_RX, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2200_rcv_frame(): chan = %d, length = %d\n", frame->chan, len));
bb5e3b2f129cc39517b925419c22f69a378ec023eh
924f3e72988efae04c4357a6686a06ba300bab18eh /*
924f3e72988efae04c4357a6686a06ba300bab18eh * Skip the frame header, get the real data from the input
924f3e72988efae04c4357a6686a06ba300bab18eh */
924f3e72988efae04c4357a6686a06ba300bab18eh data += sizeof (struct ipw2200_frame);
924f3e72988efae04c4357a6686a06ba300bab18eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh m = allocb(len, BPRI_MED);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (m) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh (void) memcpy(m->b_wptr, data, len);
bb5e3b2f129cc39517b925419c22f69a378ec023eh m->b_wptr += len;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (ic->ic_state == IEEE80211_S_SCAN) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh ic->ic_ibss_chan = &ic->ic_sup_channels[frame->chan];
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2200_fix_channel(ic, m);
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
924f3e72988efae04c4357a6686a06ba300bab18eh wh = (struct ieee80211_frame *)m->b_rptr;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh in = ieee80211_find_rxnode(ic, wh);
924f3e72988efae04c4357a6686a06ba300bab18eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_DBG(IPW2200_DBG_RX, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2200_rcv_frame(): "
924f3e72988efae04c4357a6686a06ba300bab18eh "type = %x, subtype = %x, i_fc[1] = %x, "
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ni_esslen:%d, ni_essid[0-5]:%c%c%c%c%c%c\n",
924f3e72988efae04c4357a6686a06ba300bab18eh wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK,
924f3e72988efae04c4357a6686a06ba300bab18eh wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK,
924f3e72988efae04c4357a6686a06ba300bab18eh wh->i_fc[1] & IEEE80211_FC1_WEP,
bb5e3b2f129cc39517b925419c22f69a378ec023eh in->in_esslen,
bb5e3b2f129cc39517b925419c22f69a378ec023eh in->in_essid[0], in->in_essid[1], in->in_essid[2],
bb5e3b2f129cc39517b925419c22f69a378ec023eh in->in_essid[3], in->in_essid[4], in->in_essid[5]));
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh (void) ieee80211_input(ic, m, in, frame->rssi_dbm, 0);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh ieee80211_free_node(in);
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh else
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_WARN((sc->sc_dip, CE_WARN,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2200_rcv_frame(): "
bb5e3b2f129cc39517b925419c22f69a378ec023eh "cannot allocate receive message(%u)\n",
bb5e3b2f129cc39517b925419c22f69a378ec023eh LE_16(frame->len)));
bb5e3b2f129cc39517b925419c22f69a378ec023eh}
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic void
bb5e3b2f129cc39517b925419c22f69a378ec023ehipw2200_rcv_notif(struct ipw2200_softc *sc, struct ipw2200_notif *notif)
bb5e3b2f129cc39517b925419c22f69a378ec023eh{
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct ieee80211com *ic = &sc->sc_ic;
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct ipw2200_notif_association *assoc;
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct ipw2200_notif_authentication *auth;
bb5e3b2f129cc39517b925419c22f69a378ec023eh uint8_t *ndata = (uint8_t *)notif;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_DBG(IPW2200_DBG_NOTIF, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2200_rcv_notif(): type=%u\n", notif->type));
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh ndata += sizeof (struct ipw2200_notif);
bb5e3b2f129cc39517b925419c22f69a378ec023eh switch (notif->type) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh case IPW2200_NOTIF_TYPE_ASSOCIATION:
bb5e3b2f129cc39517b925419c22f69a378ec023eh assoc = (struct ipw2200_notif_association *)ndata;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_DBG(IPW2200_DBG_WIFI, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2200_rcv_notif(): association=%u,%u\n",
bb5e3b2f129cc39517b925419c22f69a378ec023eh assoc->state, assoc->status));
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh switch (assoc->state) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh case IPW2200_ASSOC_SUCCESS:
924f3e72988efae04c4357a6686a06ba300bab18eh sc->sc_flags |= IPW2200_FLAG_ASSOCIATED;
bb5e3b2f129cc39517b925419c22f69a378ec023eh ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
bb5e3b2f129cc39517b925419c22f69a378ec023eh break;
bb5e3b2f129cc39517b925419c22f69a378ec023eh case IPW2200_ASSOC_FAIL:
924f3e72988efae04c4357a6686a06ba300bab18eh sc->sc_flags &= ~IPW2200_FLAG_ASSOCIATED;
924f3e72988efae04c4357a6686a06ba300bab18eh ieee80211_begin_scan(ic, 1);
bb5e3b2f129cc39517b925419c22f69a378ec023eh break;
bb5e3b2f129cc39517b925419c22f69a378ec023eh default:
bb5e3b2f129cc39517b925419c22f69a378ec023eh break;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh break;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh case IPW2200_NOTIF_TYPE_AUTHENTICATION:
bb5e3b2f129cc39517b925419c22f69a378ec023eh auth = (struct ipw2200_notif_authentication *)ndata;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_DBG(IPW2200_DBG_WIFI, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2200_rcv_notif(): authentication=%u\n", auth->state));
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh switch (auth->state) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh case IPW2200_AUTH_SUCCESS:
bb5e3b2f129cc39517b925419c22f69a378ec023eh ieee80211_new_state(ic, IEEE80211_S_ASSOC, -1);
bb5e3b2f129cc39517b925419c22f69a378ec023eh break;
bb5e3b2f129cc39517b925419c22f69a378ec023eh case IPW2200_AUTH_FAIL:
924f3e72988efae04c4357a6686a06ba300bab18eh sc->sc_flags &= ~IPW2200_FLAG_ASSOCIATED;
bb5e3b2f129cc39517b925419c22f69a378ec023eh break;
bb5e3b2f129cc39517b925419c22f69a378ec023eh default:
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_DBG(IPW2200_DBG_NOTIF, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2200_rcv_notif(): "
bb5e3b2f129cc39517b925419c22f69a378ec023eh "unknown authentication state(%u)\n", auth->state));
bb5e3b2f129cc39517b925419c22f69a378ec023eh break;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh break;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh case IPW2200_NOTIF_TYPE_SCAN_CHANNEL:
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_DBG(IPW2200_DBG_SCAN, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2200_rcv_notif(): scan-channel=%u\n",
bb5e3b2f129cc39517b925419c22f69a378ec023eh ((struct ipw2200_notif_scan_channel *)ndata)->nchan));
bb5e3b2f129cc39517b925419c22f69a378ec023eh break;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh case IPW2200_NOTIF_TYPE_SCAN_COMPLETE:
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_DBG(IPW2200_DBG_SCAN, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2200_rcv_notif():scan-completed,(%u,%u)\n",
bb5e3b2f129cc39517b925419c22f69a378ec023eh ((struct ipw2200_notif_scan_complete *)ndata)->nchan,
bb5e3b2f129cc39517b925419c22f69a378ec023eh ((struct ipw2200_notif_scan_complete *)ndata)->status));
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * scan complete
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_flags &= ~IPW2200_FLAG_SCANNING;
bb5e3b2f129cc39517b925419c22f69a378ec023eh ieee80211_end_scan(ic);
bb5e3b2f129cc39517b925419c22f69a378ec023eh break;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh case IPW2200_NOTIF_TYPE_BEACON:
bb5e3b2f129cc39517b925419c22f69a378ec023eh case IPW2200_NOTIF_TYPE_CALIBRATION:
bb5e3b2f129cc39517b925419c22f69a378ec023eh case IPW2200_NOTIF_TYPE_NOISE:
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * just ignore
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh break;
bb5e3b2f129cc39517b925419c22f69a378ec023eh default:
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_DBG(IPW2200_DBG_NOTIF, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2200_rcv_notif(): unknown notification type(%u)\n",
bb5e3b2f129cc39517b925419c22f69a378ec023eh notif->type));
bb5e3b2f129cc39517b925419c22f69a378ec023eh break;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh}
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic uint_t
bb5e3b2f129cc39517b925419c22f69a378ec023ehipw2200_intr(caddr_t arg)
bb5e3b2f129cc39517b925419c22f69a378ec023eh{
922d2c76afbee21520ffa2088c4e60dcb80d3945eh struct ipw2200_softc *sc = (struct ipw2200_softc *)(uintptr_t)arg;
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct ieee80211com *ic = &sc->sc_ic;
bb5e3b2f129cc39517b925419c22f69a378ec023eh uint32_t ireg, ridx, len, i;
bb5e3b2f129cc39517b925419c22f69a378ec023eh uint8_t *p, *rxbuf;
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct dma_region *dr;
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct ipw2200_hdr *hdr;
bb5e3b2f129cc39517b925419c22f69a378ec023eh uint32_t widx;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
922d2c76afbee21520ffa2088c4e60dcb80d3945eh /* when it is on suspend, unclaim all interrupt directly */
922d2c76afbee21520ffa2088c4e60dcb80d3945eh if (sc->sc_flags & IPW2200_FLAG_SUSPEND)
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (DDI_INTR_UNCLAIMED);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
922d2c76afbee21520ffa2088c4e60dcb80d3945eh /* unclaim interrupt when it is not for iwi */
922d2c76afbee21520ffa2088c4e60dcb80d3945eh ireg = ipw2200_csr_get32(sc, IPW2200_CSR_INTR);
922d2c76afbee21520ffa2088c4e60dcb80d3945eh if (ireg == 0xffffffff ||
922d2c76afbee21520ffa2088c4e60dcb80d3945eh !(ireg & IPW2200_INTR_MASK_ALL))
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (DDI_INTR_UNCLAIMED);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * mask all interrupts
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2200_csr_put32(sc, IPW2200_CSR_INTR_MASK, 0);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * acknowledge all fired interrupts
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2200_csr_put32(sc, IPW2200_CSR_INTR, ireg);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_DBG(IPW2200_DBG_INT, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2200_intr(): enter. interrupt fired, int=0x%08x\n", ireg));
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (ireg & IPW2200_INTR_MASK_ERR) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2200_DBG(IPW2200_DBG_FATAL, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2200 interrupt(): int= 0x%08x\n", ireg));
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * inform mfthread to recover hw error by stopping it
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh mutex_enter(&sc->sc_mflock);
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_flags |= IPW2200_FLAG_HW_ERR_RECOVER;
bb5e3b2f129cc39517b925419c22f69a378ec023eh mutex_exit(&sc->sc_mflock);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
922d2c76afbee21520ffa2088c4e60dcb80d3945eh goto enable_interrupt;
922d2c76afbee21520ffa2088c4e60dcb80d3945eh }
924f3e72988efae04c4357a6686a06ba300bab18eh
922d2c76afbee21520ffa2088c4e60dcb80d3945eh /*
922d2c76afbee21520ffa2088c4e60dcb80d3945eh * FW intr
922d2c76afbee21520ffa2088c4e60dcb80d3945eh */
922d2c76afbee21520ffa2088c4e60dcb80d3945eh if (ireg & IPW2200_INTR_FW_INITED) {
922d2c76afbee21520ffa2088c4e60dcb80d3945eh mutex_enter(&sc->sc_ilock);
922d2c76afbee21520ffa2088c4e60dcb80d3945eh sc->sc_fw_ok = 1;
922d2c76afbee21520ffa2088c4e60dcb80d3945eh cv_signal(&sc->sc_fw_cond);
922d2c76afbee21520ffa2088c4e60dcb80d3945eh mutex_exit(&sc->sc_ilock);
922d2c76afbee21520ffa2088c4e60dcb80d3945eh }
9e2cd38c103ae52a41b09823a11c9b5c059555f0eh
922d2c76afbee21520ffa2088c4e60dcb80d3945eh /*
922d2c76afbee21520ffa2088c4e60dcb80d3945eh * Radio OFF
922d2c76afbee21520ffa2088c4e60dcb80d3945eh */
922d2c76afbee21520ffa2088c4e60dcb80d3945eh if (ireg & IPW2200_INTR_RADIO_OFF) {
922d2c76afbee21520ffa2088c4e60dcb80d3945eh IPW2200_REPORT((sc->sc_dip, CE_CONT,
922d2c76afbee21520ffa2088c4e60dcb80d3945eh "ipw2200_intr(): radio is OFF\n"));
924f3e72988efae04c4357a6686a06ba300bab18eh
924f3e72988efae04c4357a6686a06ba300bab18eh /*
922d2c76afbee21520ffa2088c4e60dcb80d3945eh * Stop hardware, will notify LINK is down.
922d2c76afbee21520ffa2088c4e60dcb80d3945eh * Need a better scan solution to ensure
922d2c76afbee21520ffa2088c4e60dcb80d3945eh * table has right value.
924f3e72988efae04c4357a6686a06ba300bab18eh */
922d2c76afbee21520ffa2088c4e60dcb80d3945eh ipw2200_stop(sc);
922d2c76afbee21520ffa2088c4e60dcb80d3945eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh
922d2c76afbee21520ffa2088c4e60dcb80d3945eh /*
922d2c76afbee21520ffa2088c4e60dcb80d3945eh * CMD intr
922d2c76afbee21520ffa2088c4e60dcb80d3945eh */
922d2c76afbee21520ffa2088c4e60dcb80d3945eh if (ireg & IPW2200_INTR_CMD_TRANSFER) {
922d2c76afbee21520ffa2088c4e60dcb80d3945eh mutex_enter(&sc->sc_cmd_lock);
922d2c76afbee21520ffa2088c4e60dcb80d3945eh ridx = ipw2200_csr_get32(sc,
922d2c76afbee21520ffa2088c4e60dcb80d3945eh IPW2200_CSR_CMD_READ_INDEX);
922d2c76afbee21520ffa2088c4e60dcb80d3945eh i = RING_FORWARD(sc->sc_cmd_cur,
922d2c76afbee21520ffa2088c4e60dcb80d3945eh sc->sc_cmd_free, IPW2200_CMD_RING_SIZE);
922d2c76afbee21520ffa2088c4e60dcb80d3945eh len = RING_FLEN(i, ridx, IPW2200_CMD_RING_SIZE);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
922d2c76afbee21520ffa2088c4e60dcb80d3945eh IPW2200_DBG(IPW2200_DBG_INT, (sc->sc_dip, CE_CONT,
922d2c76afbee21520ffa2088c4e60dcb80d3945eh "ipw2200_intr(): cmd-ring,i=%u,ridx=%u,len=%u\n",
922d2c76afbee21520ffa2088c4e60dcb80d3945eh i, ridx, len));
922d2c76afbee21520ffa2088c4e60dcb80d3945eh
922d2c76afbee21520ffa2088c4e60dcb80d3945eh if (len > 0) {
922d2c76afbee21520ffa2088c4e60dcb80d3945eh sc->sc_cmd_free += len;
922d2c76afbee21520ffa2088c4e60dcb80d3945eh cv_signal(&sc->sc_cmd_cond);
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
922d2c76afbee21520ffa2088c4e60dcb80d3945eh for (; i != ridx;
922d2c76afbee21520ffa2088c4e60dcb80d3945eh i = RING_FORWARD(i, 1, IPW2200_CMD_RING_SIZE))
922d2c76afbee21520ffa2088c4e60dcb80d3945eh sc->sc_done[i] = 1;
922d2c76afbee21520ffa2088c4e60dcb80d3945eh mutex_exit(&sc->sc_cmd_lock);
924f3e72988efae04c4357a6686a06ba300bab18eh
922d2c76afbee21520ffa2088c4e60dcb80d3945eh mutex_enter(&sc->sc_ilock);
922d2c76afbee21520ffa2088c4e60dcb80d3945eh cv_signal(&sc->sc_cmd_status_cond);
922d2c76afbee21520ffa2088c4e60dcb80d3945eh mutex_exit(&sc->sc_ilock);
922d2c76afbee21520ffa2088c4e60dcb80d3945eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh
922d2c76afbee21520ffa2088c4e60dcb80d3945eh /*
922d2c76afbee21520ffa2088c4e60dcb80d3945eh * RX intr
922d2c76afbee21520ffa2088c4e60dcb80d3945eh */
922d2c76afbee21520ffa2088c4e60dcb80d3945eh if (ireg & IPW2200_INTR_RX_TRANSFER) {
922d2c76afbee21520ffa2088c4e60dcb80d3945eh ridx = ipw2200_csr_get32(sc,
922d2c76afbee21520ffa2088c4e60dcb80d3945eh IPW2200_CSR_RX_READ_INDEX);
922d2c76afbee21520ffa2088c4e60dcb80d3945eh widx = ipw2200_csr_get32(sc,
922d2c76afbee21520ffa2088c4e60dcb80d3945eh IPW2200_CSR_RX_WRITE_INDEX);
922d2c76afbee21520ffa2088c4e60dcb80d3945eh
922d2c76afbee21520ffa2088c4e60dcb80d3945eh IPW2200_DBG(IPW2200_DBG_INT, (sc->sc_dip, CE_CONT,
922d2c76afbee21520ffa2088c4e60dcb80d3945eh "ipw2200_intr(): rx-ring,widx=%u,ridx=%u\n",
922d2c76afbee21520ffa2088c4e60dcb80d3945eh ridx, widx));
922d2c76afbee21520ffa2088c4e60dcb80d3945eh
922d2c76afbee21520ffa2088c4e60dcb80d3945eh for (; sc->sc_rx_cur != ridx;
922d2c76afbee21520ffa2088c4e60dcb80d3945eh sc->sc_rx_cur = RING_FORWARD(sc->sc_rx_cur, 1,
922d2c76afbee21520ffa2088c4e60dcb80d3945eh IPW2200_RX_RING_SIZE)) {
922d2c76afbee21520ffa2088c4e60dcb80d3945eh i = sc->sc_rx_cur;
922d2c76afbee21520ffa2088c4e60dcb80d3945eh rxbuf = sc->sc_rxbufs[i];
922d2c76afbee21520ffa2088c4e60dcb80d3945eh dr = &sc->sc_dma_rxbufs[i];
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
922d2c76afbee21520ffa2088c4e60dcb80d3945eh * DMA sync
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
922d2c76afbee21520ffa2088c4e60dcb80d3945eh (void) ddi_dma_sync(dr->dr_hnd, 0,
922d2c76afbee21520ffa2088c4e60dcb80d3945eh IPW2200_RXBUF_SIZE, DDI_DMA_SYNC_FORKERNEL);
922d2c76afbee21520ffa2088c4e60dcb80d3945eh /*
922d2c76afbee21520ffa2088c4e60dcb80d3945eh * Get rx header(hdr) and rx data(p) from rxbuf
922d2c76afbee21520ffa2088c4e60dcb80d3945eh */
922d2c76afbee21520ffa2088c4e60dcb80d3945eh p = rxbuf;
922d2c76afbee21520ffa2088c4e60dcb80d3945eh hdr = (struct ipw2200_hdr *)p;
922d2c76afbee21520ffa2088c4e60dcb80d3945eh p += sizeof (struct ipw2200_hdr);
924f3e72988efae04c4357a6686a06ba300bab18eh
922d2c76afbee21520ffa2088c4e60dcb80d3945eh IPW2200_DBG(IPW2200_DBG_INT, (sc->sc_dip, CE_CONT,
922d2c76afbee21520ffa2088c4e60dcb80d3945eh "ipw2200_intr(): Rx hdr type %u\n",
922d2c76afbee21520ffa2088c4e60dcb80d3945eh hdr->type));
922d2c76afbee21520ffa2088c4e60dcb80d3945eh
922d2c76afbee21520ffa2088c4e60dcb80d3945eh switch (hdr->type) {
922d2c76afbee21520ffa2088c4e60dcb80d3945eh case IPW2200_HDR_TYPE_FRAME:
922d2c76afbee21520ffa2088c4e60dcb80d3945eh ipw2200_rcv_frame(sc,
922d2c76afbee21520ffa2088c4e60dcb80d3945eh (struct ipw2200_frame *)p);
922d2c76afbee21520ffa2088c4e60dcb80d3945eh break;
922d2c76afbee21520ffa2088c4e60dcb80d3945eh
922d2c76afbee21520ffa2088c4e60dcb80d3945eh case IPW2200_HDR_TYPE_NOTIF:
922d2c76afbee21520ffa2088c4e60dcb80d3945eh ipw2200_rcv_notif(sc,
922d2c76afbee21520ffa2088c4e60dcb80d3945eh (struct ipw2200_notif *)p);
922d2c76afbee21520ffa2088c4e60dcb80d3945eh break;
922d2c76afbee21520ffa2088c4e60dcb80d3945eh
922d2c76afbee21520ffa2088c4e60dcb80d3945eh default:
922d2c76afbee21520ffa2088c4e60dcb80d3945eh IPW2200_DBG(IPW2200_DBG_INT, (sc->sc_dip,
bb5e3b2f129cc39517b925419c22f69a378ec023eh CE_CONT,
922d2c76afbee21520ffa2088c4e60dcb80d3945eh "ipw2200_intr(): unknown Rx hdr type %u\n",
922d2c76afbee21520ffa2088c4e60dcb80d3945eh hdr->type));
922d2c76afbee21520ffa2088c4e60dcb80d3945eh break;
924f3e72988efae04c4357a6686a06ba300bab18eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
922d2c76afbee21520ffa2088c4e60dcb80d3945eh /*
922d2c76afbee21520ffa2088c4e60dcb80d3945eh * write sc_rx_cur backward 1 step into RX_WRITE_INDEX
922d2c76afbee21520ffa2088c4e60dcb80d3945eh */
922d2c76afbee21520ffa2088c4e60dcb80d3945eh ipw2200_csr_put32(sc, IPW2200_CSR_RX_WRITE_INDEX,
922d2c76afbee21520ffa2088c4e60dcb80d3945eh RING_BACKWARD(sc->sc_rx_cur, 1,
922d2c76afbee21520ffa2088c4e60dcb80d3945eh IPW2200_RX_RING_SIZE));
922d2c76afbee21520ffa2088c4e60dcb80d3945eh }
922d2c76afbee21520ffa2088c4e60dcb80d3945eh
922d2c76afbee21520ffa2088c4e60dcb80d3945eh /*
922d2c76afbee21520ffa2088c4e60dcb80d3945eh * TX intr
922d2c76afbee21520ffa2088c4e60dcb80d3945eh */
922d2c76afbee21520ffa2088c4e60dcb80d3945eh if (ireg & IPW2200_INTR_TX1_TRANSFER) {
922d2c76afbee21520ffa2088c4e60dcb80d3945eh mutex_enter(&sc->sc_tx_lock);
922d2c76afbee21520ffa2088c4e60dcb80d3945eh ridx = ipw2200_csr_get32(sc,
922d2c76afbee21520ffa2088c4e60dcb80d3945eh IPW2200_CSR_TX1_READ_INDEX);
922d2c76afbee21520ffa2088c4e60dcb80d3945eh len = RING_FLEN(RING_FORWARD(sc->sc_tx_cur,
922d2c76afbee21520ffa2088c4e60dcb80d3945eh sc->sc_tx_free, IPW2200_TX_RING_SIZE),
922d2c76afbee21520ffa2088c4e60dcb80d3945eh ridx, IPW2200_TX_RING_SIZE);
922d2c76afbee21520ffa2088c4e60dcb80d3945eh sc->sc_tx_free += len;
922d2c76afbee21520ffa2088c4e60dcb80d3945eh IPW2200_DBG(IPW2200_DBG_RING, (sc->sc_dip, CE_CONT,
922d2c76afbee21520ffa2088c4e60dcb80d3945eh "ipw2200_intr(): tx-ring,ridx=%u,len=%u\n",
922d2c76afbee21520ffa2088c4e60dcb80d3945eh ridx, len));
922d2c76afbee21520ffa2088c4e60dcb80d3945eh mutex_exit(&sc->sc_tx_lock);
922d2c76afbee21520ffa2088c4e60dcb80d3945eh
922d2c76afbee21520ffa2088c4e60dcb80d3945eh mutex_enter(&sc->sc_resched_lock);
922d2c76afbee21520ffa2088c4e60dcb80d3945eh if ((sc->sc_tx_free > IPW2200_TX_RING_MIN) &&
922d2c76afbee21520ffa2088c4e60dcb80d3945eh (sc->sc_flags & IPW2200_FLAG_TX_SCHED)) {
922d2c76afbee21520ffa2088c4e60dcb80d3945eh IPW2200_DBG(IPW2200_DBG_RING, (sc->sc_dip,
922d2c76afbee21520ffa2088c4e60dcb80d3945eh CE_CONT,
922d2c76afbee21520ffa2088c4e60dcb80d3945eh "ipw2200_intr(): Need Reschedule!"));
922d2c76afbee21520ffa2088c4e60dcb80d3945eh sc->sc_flags &= ~IPW2200_FLAG_TX_SCHED;
922d2c76afbee21520ffa2088c4e60dcb80d3945eh mac_tx_update(ic->ic_mach);
922d2c76afbee21520ffa2088c4e60dcb80d3945eh }
922d2c76afbee21520ffa2088c4e60dcb80d3945eh mutex_exit(&sc->sc_resched_lock);
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh
922d2c76afbee21520ffa2088c4e60dcb80d3945ehenable_interrupt:
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * enable all interrupts
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2200_csr_put32(sc, IPW2200_CSR_INTR_MASK, IPW2200_INTR_MASK_ALL);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (DDI_INTR_CLAIMED);
bb5e3b2f129cc39517b925419c22f69a378ec023eh}
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh/*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * Module Loading Data & Entry Points
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023ehDDI_DEFINE_STREAM_OPS(ipw2200_devops, nulldev, nulldev, ipw2200_attach,
14d912249090fc833b92625af4f618803de6a6c6fei feng - Sun Microsystems - Beijing China ipw2200_detach, nodev, NULL, D_MP, NULL, ipw2200_quiesce);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic struct modldrv ipw2200_modldrv = {
bb5e3b2f129cc39517b925419c22f69a378ec023eh &mod_driverops,
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2200_ident,
bb5e3b2f129cc39517b925419c22f69a378ec023eh &ipw2200_devops
bb5e3b2f129cc39517b925419c22f69a378ec023eh};
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic struct modlinkage ipw2200_modlinkage = {
bb5e3b2f129cc39517b925419c22f69a378ec023eh MODREV_1,
bb5e3b2f129cc39517b925419c22f69a378ec023eh &ipw2200_modldrv,
bb5e3b2f129cc39517b925419c22f69a378ec023eh NULL
bb5e3b2f129cc39517b925419c22f69a378ec023eh};
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023ehint
bb5e3b2f129cc39517b925419c22f69a378ec023eh_init(void)
bb5e3b2f129cc39517b925419c22f69a378ec023eh{
bb5e3b2f129cc39517b925419c22f69a378ec023eh int status;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh status = ddi_soft_state_init(&ipw2200_ssp,
bb5e3b2f129cc39517b925419c22f69a378ec023eh sizeof (struct ipw2200_softc), 1);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (status != DDI_SUCCESS)
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (status);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh mac_init_ops(&ipw2200_devops, IPW2200_DRV_NAME);
bb5e3b2f129cc39517b925419c22f69a378ec023eh status = mod_install(&ipw2200_modlinkage);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (status != DDI_SUCCESS) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh mac_fini_ops(&ipw2200_devops);
bb5e3b2f129cc39517b925419c22f69a378ec023eh ddi_soft_state_fini(&ipw2200_ssp);
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (status);
bb5e3b2f129cc39517b925419c22f69a378ec023eh}
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023ehint
bb5e3b2f129cc39517b925419c22f69a378ec023eh_fini(void)
bb5e3b2f129cc39517b925419c22f69a378ec023eh{
bb5e3b2f129cc39517b925419c22f69a378ec023eh int status;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh status = mod_remove(&ipw2200_modlinkage);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (status == DDI_SUCCESS) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh mac_fini_ops(&ipw2200_devops);
bb5e3b2f129cc39517b925419c22f69a378ec023eh ddi_soft_state_fini(&ipw2200_ssp);
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (status);
bb5e3b2f129cc39517b925419c22f69a378ec023eh}
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023ehint
bb5e3b2f129cc39517b925419c22f69a378ec023eh_info(struct modinfo *modinfop)
bb5e3b2f129cc39517b925419c22f69a378ec023eh{
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (mod_info(&ipw2200_modlinkage, modinfop));
bb5e3b2f129cc39517b925419c22f69a378ec023eh}