rt2560.c revision fb91fd8a302dfb13e250bbefb6a3970c2edc3ae3
/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* Copyright (c) 2005, 2006
* Damien Bergamini <damien.bergamini@free.fr>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*
* Ralink Technology RT2560 chipset driver
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <sys/byteorder.h>
#include <sys/ethernet.h>
#include <sys/mac_wifi.h>
#include <sys/net80211.h>
#include <sys/net80211_proto.h>
#include <inet/wifi_ioctl.h>
#include "ral_rate.h"
#include "rt2560_reg.h"
#include "rt2560_var.h"
static void *ral_soft_state_p = NULL;
#define RAL_TXBUF_SIZE (IEEE80211_MAX_LEN)
#define RAL_RXBUF_SIZE (IEEE80211_MAX_LEN)
/* quickly determine if a given rate is CCK or OFDM */
/*
* Supported rates for 802.11a/b/g modes (in 500Kbps unit).
*/
static const struct ieee80211_rateset rt2560_rateset_11a =
{ 8, { 12, 18, 24, 36, 48, 72, 96, 108 } };
static const struct ieee80211_rateset rt2560_rateset_11b =
{ 4, { 2, 4, 11, 22 } };
static const struct ieee80211_rateset rt2560_rateset_11g =
{ 12, { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 } };
static const struct {
} rt2560_def_mac[] = {
};
static const struct {
} rt2560_def_bbp[] = {
};
static const struct {
} rt2560_rf5222[] = {
};
/*
* PIO access attributes for registers
*/
static ddi_device_acc_attr_t ral_csr_accattr = {
};
/*
* DMA access attributes for descriptors: NOT to be byte swapped.
*/
static ddi_device_acc_attr_t ral_desc_accattr = {
};
/*
* Describes the chip's DMA engine
*/
static ddi_dma_attr_t ral_dma_attr = {
DMA_ATTR_V0, /* dma_attr version */
0x0000000000000000ull, /* dma_attr_addr_lo */
0xFFFFFFFFFFFFFFFFull, /* dma_attr_addr_hi */
0x00000000FFFFFFFFull, /* dma_attr_count_max */
0x0000000000000001ull, /* dma_attr_align */
0x00000FFF, /* dma_attr_burstsizes */
0x00000001, /* dma_attr_minxfer */
0x000000000000FFFFull, /* dma_attr_maxxfer */
0xFFFFFFFFFFFFFFFFull, /* dma_attr_seg */
1, /* dma_attr_sgllen */
0x00000001, /* dma_attr_granular */
0 /* dma_attr_flags */
};
/*
* device operations
*/
/*
* Module Loading Data & Entry Points
*/
static struct modldrv ral_modldrv = {
&mod_driverops, /* Type of module. This one is a driver */
"Ralink RT2500 driver v%I%", /* short description */
&ral_dev_ops /* driver specific ops */
};
static struct modlinkage modlinkage = {
(void *)&ral_modldrv,
};
static int rt2560_m_start(void *);
static void rt2560_m_stop(void *);
static int rt2560_m_promisc(void *, boolean_t);
static int rt2560_m_unicst(void *, const uint8_t *);
static mac_callbacks_t rt2560_m_callbacks = {
NULL, /* mc_resources; */
NULL /* mc_getcapab */
};
uint32_t ral_dbg_flags = 0;
void
{
if (dbg_flags & ral_dbg_flags) {
}
}
static void
{
/* update basic rate set */
/* 11b basic rates: 1, 2Mbps */
/* 11a basic rates: 6, 12, 24Mbps */
} else {
/* 11g basic rates: 1, 2, 5.5, 11, 6, 12, 24Mbps */
}
}
static void
{
/* set ON period to 70ms and OFF period to 30ms */
}
static void
{
}
static void
{
int ntries;
break;
drv_usecwait(1);
}
if (ntries == 100) {
return;
}
}
static uint8_t
{
int ntries;
if (!(val & RT2560_BBP_BUSY))
return (val & 0xff);
drv_usecwait(1);
}
return (0);
}
static void
{
int ntries;
break;
drv_usecwait(1);
}
if (ntries == 100) {
return;
}
(reg & 0x3);
/* remember last written value in sc */
}
static void
{
return;
if (IEEE80211_IS_CHAN_2GHZ(c))
else
power = 31;
/* adjust txpower using ifconfig settings */
case RT2560_RF_2522:
break;
case RT2560_RF_2523:
break;
case RT2560_RF_2524:
break;
case RT2560_RF_2525:
break;
case RT2560_RF_2525E:
break;
case RT2560_RF_2526:
break;
/* dual-band RF */
case RT2560_RF_5222:
}
break;
}
/* set Japan filter bit for channel 14 */
tmp &= ~RT2560_JAPAN_FILTER;
if (chan == 14)
/* clear CRC errors */
}
}
/*
* Refer to IEEE Std 802.11-1999 pp. 123 for more information on TSF
* synchronization.
*/
static void
{
/* first, disable TSF synchronization */
logcwmin = 5;
/* finally, enable TSF synchronization */
else
}
static void
{
/* no short preamble for 1Mbps */
/* values taken from the reference driver */
} else {
/* same values as above or'ed 0x8 */
}
}
/*
* This function can be called by ieee80211_set_shortslottime(). Refer to
* IEEE Std 802.11-1999 pp. 85 to know how these values are computed.
*/
void
{
/* slottime = (ic->ic_flags & IEEE80211_F_SHSLOT) ? 9 : 20; */
/* update the MAC slot boundaries */
}
int
{
int err;
if (err != DDI_SUCCESS)
goto fail1;
if (err != DDI_SUCCESS)
goto fail2;
if (err != DDI_SUCCESS)
goto fail3;
err = DDI_FAILURE;
goto fail4;
}
return (DDI_SUCCESS);
return (err);
}
/* ARGSUSED */
void
{
}
int
int count)
{
int i, err;
int size;
KM_SLEEP);
KM_SLEEP);
count * (sizeof (struct rt2560_tx_desc)),
if (err != DDI_SUCCESS)
goto fail1;
for (i = 0; i < count; i++) {
if (err != DDI_SUCCESS) {
while (i >= 0) {
i--;
}
goto fail2;
}
}
for (i = 0; i < count; i++) {
}
return (DDI_SUCCESS);
return (err);
}
/* ARGSUSED */
void
{
struct rt2560_tx_desc *desc;
struct rt2560_tx_data *data;
int i;
}
}
}
void
{
struct rt2560_tx_data *data;
int i;
/* tx buf */
}
}
}
void
{
/* setup tx rings */
RT2560_ATIM_RING_COUNT << 16 |
RT2560_TX_RING_COUNT << 8 |
/* rings must be initialized in this exact order */
/* setup rx ring */
}
int
int count)
{
struct rt2560_rx_desc *desc;
struct rt2560_rx_data *data;
int i, err;
int size;
ring->cur_decrypt = 0;
KM_SLEEP);
KM_SLEEP);
count * (sizeof (struct rt2560_rx_desc)),
if (err != DDI_SUCCESS)
goto fail1;
for (i = 0; i < count; i++) {
if (err != DDI_SUCCESS) {
while (i >= 0) {
i--;
}
goto fail2;
}
}
for (i = 0; i < count; i++) {
}
return (DDI_SUCCESS);
return (err);
}
/* ARGSUSED */
static void
{
int i;
}
ring->cur_decrypt = 0;
}
static void
{
int i;
/* rx buf */
}
/* ARGSUSED */
static struct ieee80211_node *
{
struct rt2560_node *rn;
}
static void
{
}
/*
* This function is called periodically (every 200ms) during scanning to
* switch from one channel to another.
*/
static void
rt2560_next_scan(void *arg)
{
(void) ieee80211_next_scan(ic);
}
/*
* This function is called for each node present in the node station table.
*/
/* ARGSUSED */
static void
{
}
/*
* This function is called periodically (every 100ms) in RUN state to update
* the rate adaptation statistics.
*/
static void
rt2560_update_rssadapt(void *arg)
{
}
static void
rt2560_statedog(void *arg)
{
enum ieee80211_state state;
sc->sc_state_id = 0;
RAL_UNLOCK(sc);
}
static int
{
enum ieee80211_state ostate;
struct ieee80211_node *ni;
int err;
if (sc->sc_scan_id != 0) {
sc->sc_scan_id = 0;
}
if (sc->sc_rssadapt_id != 0) {
sc->sc_rssadapt_id = 0;
}
if (sc->sc_state_id != 0) {
sc->sc_state_id = 0;
}
switch (nstate) {
case IEEE80211_S_INIT:
if (ostate == IEEE80211_S_RUN) {
/* abort TSF synchronization */
/* turn association led off */
rt2560_update_led(sc, 0, 0);
}
break;
case IEEE80211_S_SCAN:
break;
case IEEE80211_S_AUTH:
break;
case IEEE80211_S_ASSOC:
break;
case IEEE80211_S_RUN:
}
/* turn assocation led on */
}
break;
}
RAL_UNLOCK(sc);
/*
* Finally, start any timers.
*/
if (nstate == IEEE80211_S_RUN)
return (err);
}
/*
* Read 16 bits at address 'addr' from the serial EEPROM (either 93C46 or
* 93C66).
*/
static uint16_t
{
int n;
/* clock C once before the first command */
RT2560_EEPROM_CTL(sc, 0);
/* write start bit (1) */
/* write READ opcode (10) */
/* write address (A5-A0 or A7-A0) */
for (; n >= 0; n--) {
}
/* read data Q15-Q0 */
val = 0;
for (n = 15; n >= 0; n--) {
}
RT2560_EEPROM_CTL(sc, 0);
/* clear Chip Select and clock C */
RT2560_EEPROM_CTL(sc, 0);
return (val);
}
static void
{
struct rt2560_tx_desc *desc;
struct rt2560_tx_data *data;
struct rt2560_node *rn;
struct dma_region *dr;
int count;
for (;;) {
break;
case RT2560_TX_SUCCESS:
}
break;
case RT2560_TX_SUCCESS_RETRY:
"data frame sent after %u retries\n",
sc->sc_tx_retries++;
break;
case RT2560_TX_FAIL_RETRY:
"sending data frame failed (too much retries)\n");
}
break;
case RT2560_TX_FAIL_INVALID:
case RT2560_TX_FAIL_OTHER:
default:
break;
}
/* descriptor is no longer valid */
if (sc->sc_need_sched &&
sc->sc_need_sched = 0;
}
}
sc->sc_tx_timer = 0;
}
static void
{
struct rt2560_tx_desc *desc;
struct rt2560_tx_data *data;
struct dma_region *dr;
int count;
for (;;) {
break;
case RT2560_TX_SUCCESS:
break;
case RT2560_TX_SUCCESS_RETRY:
"mgt frame sent after %u retries\n",
break;
case RT2560_TX_FAIL_RETRY:
"sending mgt frame failed (too much " "retries)\n");
break;
case RT2560_TX_FAIL_INVALID:
case RT2560_TX_FAIL_OTHER:
default:
}
/* descriptor is no longer valid */
}
sc->sc_tx_timer = 0;
}
/*
* Some frames were received. Pass them to the hardware cipher engine before
* sending them to the 802.11 layer.
*/
void
{
struct rt2560_rx_desc *desc;
struct rt2560_rx_data *data;
struct ieee80211_frame *wh;
struct ieee80211_node *ni;
struct rt2560_node *rn;
mblk_t *m;
char *rxbuf;
int count;
for (;;) {
break;
/*
* This should not happen since we did not request
* to receive those frames when we filled RXCSR0.
*/
}
}
goto skip;
}
if ((len < sizeof (struct ieee80211_frame_min)) ||
(len > RAL_RXBUF_SIZE)) {
goto skip;
}
" allocate mblk failed.\n");
sc->sc_rx_nobuf++;
goto skip;
}
/* give rssi to the rate adatation algorithm */
/* send the frame to the 802.11 layer */
/* node is no longer needed */
}
}
{
/*
* Check if the soft interrupt is triggered by another
* driver at the same level.
*/
if (sc->sc_rx_pend) {
sc->sc_rx_pend = 0;
RAL_UNLOCK(sc);
return (DDI_INTR_CLAIMED);
}
RAL_UNLOCK(sc);
return (DDI_INTR_UNCLAIMED);
}
/*
* Return the expected ack rate for a frame transmitted at rate `rate'.
* XXX: this should depend on the destination node basic rate set.
*/
static int
{
switch (rate) {
/* CCK rates */
case 2:
return (2);
case 4:
case 11:
case 22:
/* OFDM rates */
case 12:
case 18:
return (12);
case 24:
case 36:
return (24);
case 48:
case 72:
case 96:
case 108:
return (48);
}
/* default to 1Mbps */
return (2);
}
/*
* Compute the duration (in us) needed to transmit `len' bytes at rate `rate'.
* The function automatically determines the operating mode depending on the
* given rate. `flags' indicates whether short preamble is in use or not.
*/
static uint16_t
{
if (RAL_RATE_IS_OFDM(rate)) {
/* IEEE Std 802.11a-1999, pp. 37 */
} else {
/* IEEE Std 802.11b-1999, pp. 28 */
else
}
return (txtime);
}
static uint8_t
rt2560_plcp_signal(int rate)
{
switch (rate) {
/* CCK rates (returned values are device-dependent) */
case 2: return (0x0);
case 4: return (0x1);
case 11: return (0x2);
case 22: return (0x3);
/* OFDM rates (cf IEEE Std 802.11a-1999, pp. 14 Table 80) */
case 12: return (0xb);
case 18: return (0xf);
case 24: return (0xa);
case 36: return (0xe);
case 48: return (0x9);
case 72: return (0xd);
case 96: return (0x8);
case 108: return (0xc);
/* unsupported rates (should not get there) */
default: return (0xff);
}
}
void
{
int remainder;
RT2560_AIFSN(2) |
RT2560_LOGCWMIN(3) |
RT2560_LOGCWMAX(8));
/* setup PLCP fields */
len += IEEE80211_CRC_LEN;
if (RAL_RATE_IS_OFDM(rate)) {
} else {
if (rate == 22) {
}
}
}
/* ARGSUSED */
int
{
struct rt2560_tx_desc *desc;
struct rt2560_tx_data *data;
struct ieee80211_frame *wh;
struct dma_region *dr;
struct ieee80211_node *ni;
struct ieee80211_key *k;
sc->sc_tx_nobuf++;
goto fail1;
}
if (m == NULL) {
err = DDI_FAILURE;
goto fail1;
}
}
err = DDI_FAILURE;
goto fail2;
}
/* to support shared_key auth mode */
k = ieee80211_crypto_encap(ic, m);
if (k == NULL) {
err = DDI_FAILURE;
goto fail3;
}
/* packet header may have moved, reset our local pointer */
}
flags |= RT2560_TX_ACK;
/* tell hardware to add timestamp for probe responses */
}
/* kick prio */
freemsg(m);
return (err);
}
static int
{
struct rt2560_tx_desc *desc;
struct rt2560_tx_data *data;
struct rt2560_node *rn;
struct ieee80211_rateset *rs;
struct ieee80211_frame *wh;
struct ieee80211_key *k;
struct ieee80211_node *ni;
struct dma_region *dr;
"no TX DMA buffer available!\n");
sc->sc_tx_nobuf++;
goto fail1;
}
if (m == NULL) {
err = DDI_FAILURE;
goto fail1;
}
}
err = DDI_FAILURE;
goto fail2;
}
k = ieee80211_crypto_encap(ic, m);
if (k == NULL) {
err = DDI_FAILURE;
goto fail3;
}
/* packet header may have moved, reset our local pointer */
}
/*
* the rtsthreshold (2346)
* Unnecessary codes deleted.
*/
} else {
}
if (rate <= 0) {
}
/* remember link conditions for rate adaptation algorithm */
} else
flags |= RT2560_TX_ACK;
}
/* flags |= RT2560_TX_CIPHER_NONE; */
/* kick tx */
freemsg(m);
return (err);
}
static mblk_t *
{
/*
* No data frames go out unless we're associated; this
* should not happen as the 802.11 layer does not enable
* the xmit queue until we enter the RUN state.
*/
return (NULL);
}
return (NULL);
}
}
return (mp);
}
static void
{
}
static void
{
}
static void
{
tmp &= ~RT2560_DROP_NOT_TO_ME;
}
static const char *
rt2560_get_rf(int rev)
{
switch (rev) {
case RT2560_RF_2522: return ("RT2522");
case RT2560_RF_2523: return ("RT2523");
case RT2560_RF_2524: return ("RT2524");
case RT2560_RF_2525: return ("RT2525");
case RT2560_RF_2525E: return ("RT2525e");
case RT2560_RF_2526: return ("RT2526");
case RT2560_RF_5222: return ("RT5222");
default: return ("unknown");
}
}
static void
{
int i;
/* read default values for BBP registers */
for (i = 0; i < 16; i++) {
}
/* read Tx power for all b/g channels */
for (i = 0; i < 14 / 2; i++) {
}
}
static int
{
#define N(a) (sizeof (a) / sizeof ((a)[0]))
int i, ntries;
/* wait for BBP to be ready */
break;
drv_usecwait(1);
}
if (ntries == 100) {
return (EIO);
}
/* initialize BBP registers to default values */
for (i = 0; i < N(rt2560_def_bbp); i++) {
rt2560_def_bbp[i].val);
}
return (0);
#undef N
}
static void
{
if (antenna == 1)
tx |= RT2560_BBP_ANTA;
else if (antenna == 2)
tx |= RT2560_BBP_ANTB;
else
/* need to force I/Q flip for RF 2525e, 2526 and 5222 */
tx |= RT2560_BBP_FLIPIQ;
/* update values for CCK and OFDM in BBPCSR1 */
}
static void
{
if (antenna == 1)
rx |= RT2560_BBP_ANTA;
else if (antenna == 2)
rx |= RT2560_BBP_ANTB;
else
/* need to force no I/Q flip for RF 2525e and 2526 */
rx &= ~RT2560_BBP_FLIPIQ;
}
static void
{
sc->sc_tx_timer = 0;
/* abort Tx */
/* disable Rx */
/* reset ASIC (imply reset BBP) */
/* disable interrupts */
/* reset Tx and Rx rings */
RAL_UNLOCK(sc);
}
static int
{
#define N(a) (sizeof (a) / sizeof ((a)[0]))
/* struct rt2560_softc *sc = priv; */
int i;
/* initialize MAC registers to default values */
for (i = 0; i < N(rt2560_def_mac); i++)
/* set basic rate set (will be updated later) */
rt2560_update_led(sc, 0, 0);
if (rt2560_bbp_init(sc) != 0) {
RAL_UNLOCK(sc);
return (DDI_FAILURE);
}
/* set default BSS channel */
/* kick Rx */
tmp |= RT2560_DROP_TODS;
}
/* clear old FCS and Rx FIFO errors */
/* clear any pending interrupts */
/* enable interrupts */
RAL_UNLOCK(sc);
#undef N
return (DDI_SUCCESS);
}
void
rt2560_watchdog(void *arg)
{
int ntimer = 0;
ic->ic_watchdog_timer = 0;
if (!RAL_IS_RUNNING(sc)) {
RAL_UNLOCK(sc);
return;
}
if (sc->sc_tx_timer > 0) {
if (--sc->sc_tx_timer == 0) {
RAL_UNLOCK(sc);
(void) rt2560_init(sc);
return;
}
}
ntimer = 1;
RAL_UNLOCK(sc);
if (ntimer)
}
static int
rt2560_m_start(void *arg)
{
int err;
/*
* initialize rt2560 hardware
*/
if (err != DDI_SUCCESS) {
goto fail;
}
return (err);
fail:
return (err);
}
static void
rt2560_m_stop(void *arg)
{
(void) rt2560_stop(sc);
}
static int
{
(void) rt2560_init(sc);
return (0);
}
/*ARGSUSED*/
static int
{
return (0);
}
static int
{
if (on) {
} else {
}
return (0);
}
static void
{
int err;
if (RAL_IS_RUNNING(sc)) {
RAL_UNLOCK(sc);
(void) rt2560_init(sc);
}
}
RAL_UNLOCK(sc);
}
static int
{
switch (stat) {
case MAC_STAT_IFSPEED:
break;
case MAC_STAT_NOXMTBUF:
break;
case MAC_STAT_NORCVBUF:
break;
case MAC_STAT_IERRORS:
break;
case MAC_STAT_RBYTES:
break;
case MAC_STAT_IPACKETS:
break;
case MAC_STAT_OBYTES:
break;
case MAC_STAT_OPACKETS:
break;
case MAC_STAT_OERRORS:
case WIFI_STAT_TX_FAILED:
break;
case WIFI_STAT_TX_RETRANS:
break;
case WIFI_STAT_FCS_ERRORS:
case WIFI_STAT_WEP_ERRORS:
case WIFI_STAT_TX_FRAGS:
case WIFI_STAT_MCAST_TX:
case WIFI_STAT_RTS_SUCCESS:
case WIFI_STAT_RTS_FAILURE:
case WIFI_STAT_ACK_FAILURE:
case WIFI_STAT_RX_FRAGS:
case WIFI_STAT_MCAST_RX:
case WIFI_STAT_RX_DUPS:
RAL_UNLOCK(sc);
default:
RAL_UNLOCK(sc);
return (ENOTSUP);
}
RAL_UNLOCK(sc);
return (0);
}
static uint_t
{
uint32_t r;
if (r == 0xffffffff) {
RAL_UNLOCK(sc);
return (DDI_INTR_UNCLAIMED);
}
if (!(r & RT2560_INTR_ALL)) {
RAL_UNLOCK(sc);
return (DDI_INTR_UNCLAIMED);
}
/* disable interrupts */
if (r & RT2560_TX_DONE) {
RAL_UNLOCK(sc);
}
if (r & RT2560_PRIO_DONE) {
RAL_UNLOCK(sc);
}
if (r & RT2560_RX_DONE) {
}
/* re-enable interrupts */
RAL_UNLOCK(sc);
return (DDI_INTR_CLAIMED);
}
static int
{
struct rt2560_softc *sc;
if (cmd != DDI_RESET_FORCE)
return (DDI_FAILURE);
/* abort Tx */
/* disable Rx */
/* reset ASIC (imply reset BBP) */
/* disable interrupts */
return (DDI_SUCCESS);
}
static int
{
struct rt2560_softc *sc;
struct ieee80211com *ic;
int err, i;
int instance;
char strbuf[32];
wifi_data_t wd = { 0 };
if (cmd != DDI_ATTACH)
return (DDI_FAILURE);
"unable to alloc soft_state_p\n");
return (DDI_FAILURE);
}
/* pci configuration */
&ioh);
if (err != DDI_SUCCESS) {
"ddi_regs_map_setup() failed");
goto fail1;
}
if (cachelsz == 0)
cachelsz = 0x10;
/*
* Enable response to memory space accesses,
* and enabe bus master.
*/
"set command reg to 0x%x \n", command);
/* pci i/o space */
if (err != DDI_SUCCESS) {
"ddi_regs_map_setup() failed");
goto fail1;
}
/* initialize the ral rate */
/* retrieve RT2560 rev. no */
/* retrieve MAC address */
/* retrieve RF rev. no and various other things from EEPROM */
/*
* Allocate Tx and Rx rings.
*/
if (err != DDI_SUCCESS) {
goto fail2;
}
if (err != DDI_SUCCESS) {
goto fail3;
}
if (err != DDI_SUCCESS) {
goto fail4;
}
/* set device capabilities */
IEEE80211_C_TXPMGT | /* tx power management */
IEEE80211_C_SHPREAMBLE | /* short preamble supported */
IEEE80211_C_SHSLOT; /* short slot time supported */
#define IEEE80211_CHAN_A \
/* set supported .11a rates */
/* set supported .11a channels */
for (i = 36; i <= 64; i += 4) {
}
for (i = 100; i <= 140; i += 4) {
}
for (i = 149; i <= 161; i += 4) {
}
}
/* set supported .11b and .11g rates */
/* set supported .11b and .11g channels (1 through 14) */
for (i = 1; i <= 14; i++) {
}
/* register WPA door */
/* override state transition machine */
ic->ic_def_txkey = 0;
sc->sc_rx_pend = 0;
if (err != DDI_SUCCESS) {
"ddi_add_softintr() failed");
goto fail5;
}
if (err != DDI_SUCCESS) {
"Can not get iblock cookie for INT\n");
goto fail6;
}
if (err != DDI_SUCCESS) {
"unable to add device interrupt handler\n");
goto fail6;
}
/*
* Provide initial settings for the WiFi plugin; whenever this
* information changes, we need to call mac_plugindata_update()
*/
"MAC version mismatch\n");
goto fail7;
}
if (err != 0) {
"mac_register err %x\n", err);
goto fail7;
}
/*
* Create minor node of type DDI_NT_NET_WIFI
*/
"ral", instance);
if (err != DDI_SUCCESS)
/*
* Notify link is down now
*/
return (DDI_SUCCESS);
return (DDI_FAILURE);
}
static int
{
struct rt2560_softc *sc;
if (cmd != DDI_DETACH)
return (DDI_FAILURE);
/*
* Unregister from the MAC layer subsystem
*/
return (DDI_FAILURE);
/*
* detach ieee80211 layer
*/
return (DDI_SUCCESS);
}
int
{
}
int
_init(void)
{
int status;
sizeof (struct rt2560_softc), 1);
if (status != 0)
return (status);
if (status != 0) {
}
return (status);
}
int
_fini(void)
{
int status;
if (status == 0) {
}
return (status);
}