pcan.c revision ff3124eff995e6cd8ebd8c6543648e0670920034
/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* Copyright (c) 1997, 1998, 1999
* Bill Paul <wpaul@ctr.columbia.edu>. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Bill Paul.
* 4. Neither the name of the author nor the names of any co-contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <sys/ethernet.h>
#include <sys/byteorder.h>
#include "pcan.h"
#include <sys/mac_wifi.h>
#include <inet/wifi_ioctl.h>
#ifdef DEBUG
#define PCAN_DBG_BASIC 0x1
#define PCAN_DBG_INFO 0x2
#define PCAN_DBG_SEND 0x4
#define PCAN_DBG_RCV 0x8
#define PCAN_DBG_LINKINFO 0x10
#define PCAN_DBG_FW_VERSION 0x20
#define PCAN_DBG_CMD 0x40
uint32_t pcan_debug = 0;
#define PCANDBG(x) \
#else
#define PCANDBG(x)
#endif
static ddi_device_acc_attr_t accattr = {
};
static ddi_dma_attr_t control_cmd_dma_attr = {
DMA_ATTR_V0, /* version of this structure */
0, /* lowest usable address */
0xffffffffffffffffull, /* highest usable address */
0xffffffffull, /* maximum DMAable byte count */
4, /* alignment in bytes */
0xfff, /* burst sizes (any) */
1, /* minimum transfer */
0xffffull, /* maximum transfer */
0xffffffffffffffffull, /* maximum segment length */
1, /* maximum number of segments */
1, /* granularity */
0, /* flags (reserved) */
};
void *pcan_soft_state_p = NULL;
static int pcan_device_type;
NULL,
};
static char *pcan_name_str = "pcan";
extern struct mod_ops mod_driverops;
"Cisco-Aironet 802.11b driver",
};
static struct modlinkage modlinkage = {
};
int
_init(void)
{
int stat;
/* Allocate soft state */
return (stat);
if (stat != 0) {
}
return (stat);
}
int
_fini(void)
{
int stat;
if (stat != DDI_SUCCESS)
return (stat);
return (stat);
}
int
{
}
static int
{
char *buf;
if (ret != DDI_SUCCESS)
return (DDI_PROBE_FAILURE);
#ifdef DEBUG
if (pcan_debug & PCAN_DBG_FW_VERSION) {
}
#endif
#ifdef DEBUG
if (pcan_debug & PCAN_DBG_FW_VERSION) {
}
#endif
} else {
}
return (ret);
}
static int
{
int ret;
int instance;
wifi_data_t wd = { 0 };
char strbuf[256];
if (cmd != DDI_ATTACH)
goto attach_fail1;
/*
* Since this driver is porting from freebsd, so just like
* the original driver, the minipci card doesn't work on amd64
* machine.
* For sparc, since no pci card is available for the test, so this
* version doesn't support sparc. If there is card available and
* requirement, future version will try to support sparc.
* This driver works well for minipci card on 32bit x86
* machine, so keep the code to just support minipci card on 32bit
* mode.
*/
if (pcan_device_type == PCAN_DEVICE_PCI) {
goto attach_fail1;
}
#endif /* sparc */
#if defined(__amd64)
if (pcan_device_type == PCAN_DEVICE_PCI) {
goto attach_fail1;
}
#endif /* amd64 */
/* Allocate soft state associated with this instance. */
goto attach_fail1;
}
if (ddi_regs_map_setup(dip, 0,
goto attach_fail2;
goto attach_fail3;
goto attach_fail3;
goto attach_fail3;
}
pcan_p->glds_nocarrier = 0;
pcan_p->glds_noxmtbuf = 0;
pcan_p->glds_norcvbuf = 0;
if (ddi_get_iblock_cookie(dip,
goto attach_fail3;
}
goto attach_fail3a;
}
goto attach_fail4;
}
" %x\n", ret));
goto attach_fail4;
}
} else {
goto attach_fail4;
}
/* leaves IF down, intr disabled */
goto attach_fail5;
}
}
goto attach_fail6;
}
/*
* Provide initial settings for the WiFi plugin; whenever this
* information changes, we need to call mac_pdata_update()
*/
"MAC version mismatch\n"));
goto attach_fail6;
}
if (err != 0) {
"mac_register err\n"));
goto attach_fail6;
}
/* turn on CS interrupt */
ret);
goto attach_fail7;
}
}
pcan_p->an_scan_num = 0;
goto attach_fail8;
}
}
return (DDI_SUCCESS);
if (pcan_p->an_scanlist_timeout_id != 0) {
pcan_p->an_scanlist_timeout_id = 0;
}
}
if (pcan_p->pcan_info_softint_id)
if (pcan_p->pcan_handle0)
if (pcan_p->pcan_handle1)
if (pcan_p->pcan_handle2)
}
return (DDI_FAILURE);
}
static int
{
int ret;
if (cmd != DDI_DETACH)
return (DDI_FAILURE);
return (DDI_FAILURE);
}
if (pcan_p->an_scanlist_timeout_id != 0) {
pcan_p->an_scanlist_timeout_id = 0;
}
if (pcan_p->pcan_connect_timeout_id != 0) {
}
while (scan_item0) {
}
if (ret != 0)
return (DDI_FAILURE);
if (pcan_p->pcan_handle0)
if (pcan_p->pcan_handle1)
if (pcan_p->pcan_handle2)
} else {
}
if (pcan_p->pcan_info_softint_id)
if (pcan_p->pcan_badrids_len)
return (DDI_SUCCESS);
}
/*
* card services and event handlers
*/
static int
{
int ret;
goto regcs_ret;
}
/* card is not present, why are we attaching ? */
ret = CS_NO_CARD;
goto unreg;
}
goto fail;
}
/* turn on initialization events */
goto fail;
}
/* wait for and process card insertion events */
return (CS_SUCCESS);
fail:
(void) csx_DeregisterClient(chdl);
return (ret);
}
static void
{
int ret;
/*
* The card service not registered means register_cs function
* doesnot return TRUE. Then all the lelated resource has been
* released in register_cs.
*/
return;
}
}
static void
{
}
static int
{
int ret = CS_SUCCESS;
switch (event) {
case CS_EVENT_CARD_INSERTION:
break;
break;
case CS_EVENT_CARD_REMOVAL:
if (priority & CS_EVENT_PRI_HIGH)
break;
break;
case CS_EVENT_CLIENT_INFO:
break;
break;
default:
break;
}
return (ret);
}
static int
{
goto insert_ret;
}
goto insert_ret;
}
/* verify manufacture ID */
goto insert_ret;
}
goto insert_ret;
}
/* verify function ID */
goto insert_ret;
}
goto insert_ret;
}
"pcan: config present=%x nr=%x hr=%x regs[0]=%x base=%x last=%x\n",
hi = 0;
break;
}
break;
}
}
}
}
}
}
goto insert_ret;
}
goto insert_ret;
}
goto un_io;
}
goto un_irq;
}
return (CS_SUCCESS);
return (ret);
}
/*
* assume card is already removed, don't touch the hardware
*/
static void
{
int ret;
return;
}
/*
* gld operation interface routines
*/
static int
pcan_start(void *arg)
{
return (PCAN_FAIL);
}
(void) pcan_loaddef(pcan_p);
return (PCAN_SUCCESS);
}
static void
{
return;
}
if (pcan_p->pcan_connect_timeout_id != 0) {
}
}
/*
* mac address can only be set in 'disable' state and
* be effective after 'enable' state.
*/
static int
{
int ret = PCAN_SUCCESS;
goto done;
}
goto done;
}
if (pcan_config_mac(pcan_p)) {
goto done;
}
}
done:
return (ret);
}
/*
* send a packet out for pccard
*/
static int
{
#ifdef PCAN_SEND_DEBUG
struct an_ltv_status radio_status;
#endif /* PCAN_SEND_DEBUG */
struct ieee80211_frame *wh;
int i = 0;
return (PCAN_SUCCESS); /* drop packet */
}
pcan_p->glds_nocarrier++;
return (PCAN_SUCCESS); /* drop packet */
}
return (PCAN_SUCCESS); /* drop packet */
}
/* check whether there is a xmt buffer available */
while ((i < AN_TX_RING_CNT) &&
i++;
}
if (i == AN_TX_RING_CNT) {
pcan_p->glds_noxmtbuf++;
return (PCAN_FAIL);
}
#ifdef DEBUG
if (pcan_debug & PCAN_DBG_SEND) {
}
#endif
return (PCAN_SUCCESS); /* drop packet */
}
return (PCAN_SUCCESS); /* drop packet */
}
/* initialize xmt frame header, payload_len must be stored in LE */
/*
* mblk sent down from plugin includes station mode 802.11 frame and
* llc, so we here need to remove them and add an ethernet header.
*/
+ 2;
pkt_len++;
}
#ifdef DEBUG
if (pcan_debug & PCAN_DBG_SEND) {
pkt_len);
for (i = 0; i < pkt_len + 4; i++)
*((unsigned char *)buf_p + 0x36 + i));
}
#endif
pkt_len + 12);
#ifdef PCAN_SEND_DEBUG
} else {
}
#endif /* PCAN_SEND_DEBUG */
if (ring_idx)
return (PCAN_FAIL);
else {
return (PCAN_SUCCESS);
}
}
/*
*/
static int
{
char *buf;
uint32_t i;
struct ieee80211_frame *wh;
struct an_card_tx_desc an_tx_desc;
pcan_p->glds_nocarrier++;
return (PCAN_SUCCESS); /* drop packet */
}
return (PCAN_SUCCESS); /* drop packet */
}
pcan_p->glds_noxmtbuf++;
return (PCAN_FAIL);
}
#ifdef DEBUG
if (pcan_debug & PCAN_DBG_SEND) {
}
#endif
/*
* mblk sent down from plugin includes station mode 802.11 frame and
* llc, so we here need to remove them and add an ethernet header.
*/
+ 2;
#ifdef DEBUG
if (pcan_debug & PCAN_DBG_SEND) {
"pkt_len=%x", pkt_len);
for (i = 0; i < pkt_len + 14; i++)
*((unsigned char *)buf + 0x36 + i));
}
#endif
an_tx_desc.an_offset = 0;
for (i = 0; i < sizeof (an_tx_desc) / 4; i++) {
((uint32_t *)&an_tx_desc)[i]);
}
return (PCAN_SUCCESS);
}
static mblk_t *
{
int ret = 0;
(PCAN_CARD_LINKUP | PCAN_CARD_READY)) {
return (mp);
}
}
if (ret) {
break;
}
}
return (mp);
}
/*
* this driver is porting from freebsd, the code in freebsd
* doesn't show how to set promiscous mode.
*/
/*ARGSUSED*/
static int
{
int ret = PCAN_SUCCESS;
}
return (ret);
}
/*ARGSUSED*/
static int
{
uint16_t i;
int ret = PCAN_SUCCESS;
goto done;
}
" failed \n");
goto done;
}
for (i = 0; i < ANC_STAT_CNT; i++) {
}
goto done;
}
switch (statitem) {
case MAC_STAT_IFSPEED:
break;
case MAC_STAT_NOXMTBUF:
break;
case MAC_STAT_NORCVBUF:
break;
case MAC_STAT_IERRORS:
break;
case MAC_STAT_OERRORS:
break;
case MAC_STAT_RBYTES:
break;
case MAC_STAT_IPACKETS:
break;
case MAC_STAT_OBYTES:
break;
case MAC_STAT_OPACKETS:
break;
case WIFI_STAT_TX_FAILED:
break;
case WIFI_STAT_TX_RETRANS:
break;
case WIFI_STAT_FCS_ERRORS:
break;
case WIFI_STAT_WEP_ERRORS:
break;
case WIFI_STAT_MCAST_TX:
break;
case WIFI_STAT_MCAST_RX:
break;
case WIFI_STAT_TX_FRAGS:
case WIFI_STAT_RX_FRAGS:
*val = 0;
break;
case WIFI_STAT_RTS_SUCCESS:
break;
case WIFI_STAT_RTS_FAILURE:
break;
case WIFI_STAT_ACK_FAILURE:
break;
case WIFI_STAT_RX_DUPS:
break;
default:
}
done:
return (ret);
}
/*
* this driver is porting from freebsd, the code in freebsd
* doesn't show how to set multi address.
*/
/*ARGSUSED*/
static int
{
return (PCAN_FAIL);
}
return (PCAN_SUCCESS);
}
static uint_t
{
wifi_data_t wd = { 0 };
return (DDI_INTR_UNCLAIMED);
}
if (pcan_p->pcan_connect_timeout_id != 0) {
}
sizeof (wd));
#ifdef DEBUG
if (pcan_debug & PCAN_DBG_LINKINFO) {
"ssid=\"%s\""
" (%02x:%02x:%02x:%02x:%02x:%02x)\n",
}
#endif
}
#ifdef DEBUG
if (pcan_debug & PCAN_DBG_LINKINFO) {
}
#endif
if (link != AN_LINKSTAT_SYNCLOST_HOSTREQ) {
}
}
return (DDI_INTR_CLAIMED);
}
static uint_t
{
(PCAN_CARD_READY | PCAN_CARD_INTREN)) {
return (DDI_INTR_UNCLAIMED);
}
return (DDI_INTR_UNCLAIMED);
}
if (stat & AN_EV_AWAKE) {
}
if (stat & AN_EV_LINKSTAT) {
}
}
}
if (stat & AN_EV_TX_CPY) {
}
}
}
}
}
}
if (stat & AN_EV_TX_EXC) {
}
}
}
if (stat & AN_EV_ALLOC) {
}
}
return (DDI_INTR_CLAIMED);
}
static uint_t
{
(PCAN_CARD_READY | PCAN_CARD_INTREN)) {
return (DDI_INTR_UNCLAIMED);
}
return (DDI_INTR_UNCLAIMED);
}
/* disable interrupt without ack */
return (DDI_INTR_CLAIMED);
}
/*
* retrieve data from pccard
*/
static void
{
struct ieee80211_llc *llc;
if (!mp) {
pcan_p->glds_norcvbuf++;
return;
}
if (id == AN_INVALID_FID) {
pcan_p->glds_norcvbuf++;
goto done;
}
goto done;
}
if (frm.an_rx_status) {
goto done;
}
goto done;
}
goto done;
}
goto done;
}
#ifdef DEBUG
if (pcan_debug & PCAN_DBG_RCV) {
int i;
for (i = 0; i < sizeof (frm); i++)
}
#endif
/*
* this driver deal with WEP by itself. so plugin always thinks no wep.
*/
sizeof (struct ieee80211_frame));
/*
* discard those frames which are not from the AP we connect or
* without 'ap->sta' direction
*/
goto done;
}
sizeof (struct ieee80211_frame));
/* the plugin need a llc here */
/* read in the rest of data */
goto done;
}
}
done:
if (ret) {
return;
}
#ifdef DEBUG
if (pcan_debug & PCAN_DBG_RCV) {
int i;
}
#endif
}
/*
* retrieve data from mini-pci card
*/
static void
{
struct an_card_rx_desc an_rx_desc;
char *buf;
int i, j;
struct ieee80211_frame *frm;
struct ieee80211_llc *llc;
if (!mp) {
pcan_p->glds_norcvbuf++;
return;
}
for (i = 0; i < sizeof (an_rx_desc) / 4; i++)
((uint32_t *)&an_rx_desc)[i]);
#ifdef DEBUG
if (pcan_debug & PCAN_DBG_RCV) {
data_len);
for (j = 0; j < data_len + 14; j++)
}
#endif
data_len);
goto done;
}
/*
* minipci card receive an ethernet frame, so assembly a 802.11
* frame here manually.
*/
#ifdef DEBUG
if (pcan_debug & PCAN_DBG_RCV) {
int i;
+ sizeof (*llc); i++)
}
#endif
}
done:
an_rx_desc.an_done = 0;
for (i = 0; i < sizeof (an_rx_desc) / 4; i++)
((uint32_t *)&an_rx_desc)[i]);
if (ret) {
}
}
/*ARGSUSED*/
static uint32_t
{
}
}
ret = 0;
for (i = 0; i < AN_TX_RING_CNT; i++) {
break;
}
}
}
return (ret);
}
/*
* delay in which the mutex is not hold.
* assuming the mutex has already been hold.
*/
static void
{
}
static void
{
}
}
/*
* set command without the need of ACK.
*/
static uint16_t
{
int i;
for (i = 0; i < AN_TIMEOUT; i++) {
if (!(stat & AN_CMD_BUSY))
break;
}
if (i == AN_TIMEOUT) {
drv_usecwait(10);
}
}
for (i = 0; i < AN_TIMEOUT; i++) {
break;
}
if (stat & AN_CMD_BUSY)
"stat=%x, r0=%x, r1=%x, r2=%x\n",
}
}
static uint16_t
{
int i;
if (((cmd == AN_CMD_ENABLE) &&
((cmd == AN_CMD_DISABLE) &&
return (PCAN_SUCCESS);
for (i = 0; i < AN_TIMEOUT; i++) {
if (!(stat & AN_CMD_BUSY)) {
break;
}
}
if (i == AN_TIMEOUT) {
drv_usecwait(10);
}
for (i = 0; i < AN_TIMEOUT; i++) {
break;
}
}
if (i == AN_TIMEOUT) {
if (cmd == AN_CMD_FW_RESTART) {
return (PCAN_SUCCESS);
}
#ifdef DEBUG
if (pcan_debug & PCAN_DBG_CMD) {
}
#endif
return (PCAN_TIMEDOUT_CMD);
}
for (i = 0; i < AN_TIMEOUT; i++) {
break;
}
if (cmd == AN_CMD_FW_RESTART) {
return (PCAN_SUCCESS);
}
if (i == AN_TIMEOUT) {
#ifdef DEBUG
if (pcan_debug & PCAN_DBG_CMD) {
}
#endif
} else {
if (stat & AN_STAT_CMD_RESULT) {
#ifdef DEBUG
if (pcan_debug & PCAN_DBG_CMD) {
"%x,%x,%x,%x\n",
}
#endif
} else {
ret = PCAN_SUCCESS;
}
}
if (stat & AN_CMD_BUSY)
if (ret == PCAN_SUCCESS) {
if (cmd == AN_CMD_ENABLE)
if (cmd == AN_CMD_DISABLE)
}
return (ret);
}
static uint16_t
{
int i;
if (channel) {
} else {
}
for (i = 0; i < AN_TIMEOUT; i++) {
break;
}
return (PCAN_TIMEDOUT_TARGET);
}
return (PCAN_SUCCESS);
}
static uint16_t
{
uint32_t i;
struct an_card_rid_desc an_rid_desc;
struct an_ltv_gen *an_ltv;
return (EIO);
an_rid_desc.an_rid = 0;
for (i = 0; i < sizeof (an_rid_desc) / 4; i++)
((uint32_t *)&an_rid_desc)[i]);
AN_ACCESS_READ, type, 0, 0)) {
return (EIO);
}
#ifdef DEBUG
if (pcan_debug & PCAN_DBG_INFO) {
"expected len=%d," "actual len=%d",
}
#endif
"actual: len=%d", type,
/* return (EIO); */
}
/* 1. select read mode */
return (stat);
/* 2. select Buffer Access Path (channel) 1 for PIO */
return (stat);
/* 3. read length */
}
/* 4. read value */
}
}
return (PCAN_SUCCESS);
}
static uint16_t
{
int i;
struct an_card_rid_desc an_rid_desc;
for (i = 0; i < AN_TIMEOUT; i++) {
if (!(stat & AN_CMD_BUSY)) {
break;
}
}
if (i == AN_TIMEOUT) {
}
for (i = 0; i < sizeof (an_rid_desc) / 4; i++)
((uint32_t *)&an_rid_desc)[i]);
AN_ACCESS_WRITE, type, 0, 0);
return (stat);
/* 0. select read mode first */
return (stat);
/* 1. select Buffer Access Path (channel) 1 for PIO */
return (stat);
/* 2. write length */
/* 3. write value */
val_p++;
}
/* 4. select write mode */
AN_ACCESS_WRITE, type));
}
return (PCAN_FAIL);
}
/*ARGSUSED*/
static uint16_t
{
return (PCAN_FAIL);
len >>= 1;
}
return (PCAN_SUCCESS);
}
/*ARGSUSED*/
static uint16_t
{
return (PCAN_FAIL);
len >>= 1;
}
return (PCAN_SUCCESS);
}
static uint16_t
{
if (rw != PCAN_READ_LTV) {
return (PCAN_FAIL);
}
return (ret);
return (PCAN_SUCCESS);
}
static uint16_t
{
if (rw == PCAN_READ_LTV) {
return (ret);
goto done;
}
return (ret);
done:
return (ret);
}
static uint16_t
{
if (rw != PCAN_READ_LTV) {
return (PCAN_FAIL);
}
return (ret);
return (PCAN_SUCCESS);
}
static uint16_t
{
if (rw == PCAN_READ_LTV) {
return (ret);
goto done;
}
return (ret);
done:
return (ret);
}
static uint16_t
{
if (rw == PCAN_READ_LTV) {
return (ret);
goto done;
}
return (ret);
done:
return (ret);
}
static uint16_t
struct an_ltv_scanresult *scanresult_p)
{
if (rw != PCAN_READ_LTV) {
return (PCAN_FAIL);
}
return (ret);
return (PCAN_SUCCESS);
}
static uint16_t
{
if (rw == PCAN_READ_LTV) {
return (ret);
}
goto done;
}
return (ret);
done:
return (ret);
}
static uint16_t
{
struct an_ltv_wepkey wk;
if (rw == PCAN_READ_LTV) {
return (ret);
for (i = 0; i < 5; i++) {
rid = AN_RID_WEPKEY;
}
return (PCAN_SUCCESS);
}
for (i = 0; i < MAX_NWEPKEYS; i++) {
return (ret);
}
}
/* Now set the default key */
return (ret);
}
static uint16_t
{
int i;
return (stat);
}
if (!(stat & AN_EV_ALLOC))
return (PCAN_TIMEDOUT_ALLOC);
/* zero fill the allocated NIC mem - sort of pcan_fill_ch0 */
}
return (PCAN_SUCCESS);
}
static void
{
int i, j;
struct an_card_rx_desc an_rx_desc;
for (i = 0; i < AN_MAX_RX_DESC; i++) {
an_rx_desc.an_valid = 0;
for (j = 0; j < sizeof (an_rx_desc) / 4; j++)
+ (i * sizeof (an_rx_desc))
}
}
static int
{
int i, j;
struct an_card_rid_desc an_rid_desc;
struct an_card_rx_desc an_rx_desc;
struct an_card_tx_desc an_tx_desc;
/* Allocate DMA for rx */
AN_MAX_RX_DESC) != PCAN_SUCCESS) {
goto error;
}
for (i = 0; i < AN_MAX_RX_DESC; i++) {
an_rx_desc.an_done = 0;
for (j = 0; j < sizeof (an_rx_desc) / 4; j++)
+ (i * sizeof (an_rx_desc))
}
/* Allocate DMA for tx */
AN_MAX_TX_DESC) != PCAN_SUCCESS) {
goto error;
}
for (i = 0; i < AN_MAX_TX_DESC; i++) {
an_tx_desc.an_offset = 0;
an_tx_desc.an_eoc = 0;
an_tx_desc.an_valid = 0;
an_tx_desc.an_len = 0;
for (j = 0; j < sizeof (an_tx_desc) / 4; j++)
+ (i * sizeof (an_tx_desc))
}
/* Allocate DMA for rid */
goto error;
}
an_rid_desc.an_rid = 0;
for (i = 0; i < sizeof (an_rid_desc) / 4; i++)
((uint32_t *)&an_rid_desc)[i]);
return (PCAN_SUCCESS);
return (PCAN_FAIL);
}
static int
{
/* Allocate DMA for rx */
for (i = 0; i < AN_MAX_RX_DESC; i++) {
DDI_DMA_SLEEP, 0,
goto error;
goto error;
}
len, DDI_DMA_READ |
goto error;
}
}
/* Allocate DMA for tx */
for (i = 0; i < AN_MAX_TX_DESC; i++) {
DDI_DMA_SLEEP, 0,
goto error;
goto error;
}
len, DDI_DMA_WRITE |
goto error;
}
}
/* Allocate DMA for rid */
DDI_DMA_SLEEP, 0,
goto error;
goto error;
}
len, DDI_DMA_RDWR |
goto error;
}
goto error;
}
return (PCAN_SUCCESS);
return (ret);
}
static void
{
int i;
/* free RX dma */
for (i = 0; i < AN_MAX_RX_DESC; i++) {
(void) ddi_dma_unbind_handle(
}
}
}
}
/* free TX dma */
for (i = 0; i < AN_MAX_TX_DESC; i++) {
(void) ddi_dma_unbind_handle(
}
}
}
}
/* free cmd dma */
(void) ddi_dma_unbind_handle(
}
}
}
}
/*
* get card capability (WEP, default channel), setup broadcast, mac addresses
*/
static uint32_t
{
}
}
#ifdef DEBUG
if (pcan_debug & PCAN_DBG_FW_VERSION) {
"'%s %s %s' is %s\n",
"minipci" : "pccard",
}
#endif
}
}
}
return (PCAN_SUCCESS);
}
static int
{
stat));
return ((int)stat);
}
stat));
return ((int)stat);
}
stat));
return ((int)stat);
}
if (pcan_p->pcan_usewep)
stat));
return ((int)stat);
}
&pcan_p->an_actual_config)) {
stat));
return ((int)stat);
}
stat));
return ((int)stat);
}
return (PCAN_SUCCESS);
}
static int
{
int i;
for (i = 0; i < MAX_NWEPKEYS; i++) {
}
pcan_p->an_cur_wepkey = 0;
pcan_p->pcan_usewep = 0;
i = pcan_config_mac(pcan_p);
return (i);
}
static int
{
int i;
for (i = 0; i < AN_TX_RING_CNT; i++) {
if (ret) {
"%x\n", i, ret);
return (DDI_FAILURE);
}
ring_p->an_tx_ring[i] = 0;
}
return (PCAN_SUCCESS);
}
static void
{
}
static void
{
}
/*
* for scan result
*/
static int
{
return (PCAN_FAIL);
}
pcan_p->an_scan_num++;
return (PCAN_SUCCESS);
}
static void
{
kmem_free(s, sizeof (*s));
pcan_p->an_scan_num--;
}
static void
pcan_scanlist_timeout(void *arg)
{
for (; scan_item0; ) {
scan_item0->an_timeout));
if (scan_item0->an_timeout == 0) {
} else {
scan_item0->an_timeout--;
}
}
}
/*
* for wificonfig and dlamd ioctl
*/
static int
{
uint16_t i;
char *value;
char *buf;
int iret;
struct an_ltv_status *status_p;
struct an_ltv_ssidlist *ssidlist_p;
"memory(%d)\n", MAX_BUF_LEN));
return (ENOMEM);
}
if (cmd == WLAN_GET_PARAM) {
goto done;
}
} else if (cmd == WLAN_SET_PARAM) {
} else {
return (EINVAL);
}
done:
for (i = 0; i < (outfp->wldp_length); i++) {
}
return (iret);
}
static int
{
uint16_t i;
char *buf;
int iret;
struct an_ltv_status *status_p;
struct an_ltv_aplist *aplist_p;
"memory(%d)\n", MAX_BUF_LEN));
return (ENOMEM);
}
if (cmd == WLAN_GET_PARAM) {
goto done;
}
sizeof (wl_bssid_t));
"pcan: cfg_bssid: bssid=%x %x %x %x %x %x\n",
status_p->an_cur_bssid[0],
} else if (cmd == WLAN_SET_PARAM) {
} else {
return (EINVAL);
}
done:
for (i = 0; i < (outfp->wldp_length); i++) {
}
return (iret);
}
/*ARGSUSED*/
static int
{
if ((!enable) &&
ret = (int)WL_HW_ERROR;
goto exit;
}
ret = (int)WL_HW_ERROR;
goto exit;
}
goto done;
}
do
{
i++;
} while ((!ret) && (i < 32) &&
done:
if ((!enable) &&
ret = (int)WL_HW_ERROR;
goto exit;
}
/* record the scan result for future use */
for (j = 0; j < i; j++) {
/*
* sometimes, those empty items are recorded by hardware,
* this is wrong, just ignore those items here.
*/
bssid_t, 6) == 0) {
continue;
}
/*
*/
check_num = 0;
if (scan_item0 == NULL) {
if (pcan_add_scan_item(pcan_p,
pcan_p->an_scanresult[j]) != 0) {
return (WL_SUCCESS);
}
}
for (; scan_item0; ) {
break;
} else {
check_num++;
}
}
if (pcan_add_scan_item(pcan_p,
pcan_p->an_scanresult[j]) != 0) {
return (WL_SUCCESS);
}
}
}
exit:
if (ret)
return (ret);
}
/*ARGSUSED*/
static int
{
char *buf;
uint16_t i;
"memory(%d)\n", MAX_BUF_LEN));
return (ENOMEM);
}
for (i = 0; i < pcan_p->an_scan_num; i++) {
if (!scan_item)
goto done;
i * sizeof (wl_ess_conf_t));
= WL_DSSS;
}
done:
for (i = 0; i < (outfp->wldp_length); i++)
return (WL_SUCCESS);
}
/*ARGSUSED*/
static int
{
char *buf;
uint16_t i;
"memory(%d)\n", MAX_BUF_LEN));
return (ENOMEM);
}
else
for (i = 0; i < (outfp->wldp_length); i++)
return (WL_SUCCESS);
}
static int
{
uint16_t i;
char *buf;
int iret;
struct an_ltv_genconfig *cfg_p;
"memory(%d)\n", MAX_BUF_LEN));
return (ENOMEM);
}
if (cmd == WLAN_GET_PARAM) {
}
} else if (cmd == WLAN_SET_PARAM) {
} else {
return (EINVAL);
}
for (i = 0; i < (outfp->wldp_length); i++)
return (iret);
}
static int
{
char *buf;
int iret;
struct an_ltv_genconfig *cfg_p;
struct an_ltv_status *status_p;
"memory(%d)\n", MAX_BUF_LEN));
return (ENOMEM);
}
if (cmd == WLAN_GET_PARAM) {
goto done;
}
} else if (cmd == WLAN_SET_PARAM) {
goto done;
}
} else {
return (EINVAL);
}
done:
for (i = 0; i < (outfp->wldp_length); i++)
return (iret);
}
/*ARGSUSED*/
static int
{
uint16_t i;
char *buf;
int iret;
struct an_ltv_genconfig *cfg_p;
struct an_ltv_genconfig *actcfg_p;
"memory(%d)\n", MAX_BUF_LEN));
return (ENOMEM);
}
if (cmd == WLAN_GET_PARAM) {
goto done;
}
break;
}
= rates;
} else if (cmd == WLAN_SET_PARAM) {
i++) {
}
} else {
return (EINVAL);
}
done:
for (i = 0; i < (outfp->wldp_length); i++)
return (iret);
}
/*ARGSUSED*/
static int
{
uint16_t i;
int iret;
char *buf;
"memory(%d)\n", MAX_BUF_LEN));
return (ENOMEM);
}
if (cmd == WLAN_GET_PARAM) {
= WL_RATE_1M;
= WL_RATE_2M;
= WL_RATE_5_5M;
= WL_RATE_11M;
4 * sizeof (char);
} else {
return (EINVAL);
}
done:
for (i = 0; i < (outfp->wldp_length); i++)
return (iret);
}
/*ARGSUSED*/
static int
{
uint16_t i;
char *buf;
int iret;
struct an_ltv_genconfig *actcfg_p;
"memory(%d)\n", MAX_BUF_LEN));
return (ENOMEM);
}
if (cmd == WLAN_GET_PARAM) {
goto done;
}
sizeof (wl_ps_mode_t);
} else if (cmd == WLAN_SET_PARAM) {
} else {
return (EINVAL);
}
done:
for (i = 0; i < (outfp->wldp_length); i++)
return (iret);
}
static int
{
uint16_t i;
char *buf;
int iret;
struct an_ltv_genconfig *cfg_p;
struct an_ltv_genconfig *actcfg_p;
"memory(%d)\n", MAX_BUF_LEN));
return (ENOMEM);
}
if (cmd == WLAN_GET_PARAM) {
} else {
}
} else if (cmd == WLAN_SET_PARAM) {
} else {
}
} else {
return (EINVAL);
}
actcfg_p->an_authtype));
for (i = 0; i < (outfp->wldp_length); i++)
return (iret);
}
static int
{
uint16_t i;
char *buf;
int iret;
struct an_ltv_genconfig *cfg_p;
"memory(%d)\n", MAX_BUF_LEN));
return (ENOMEM);
}
if (cmd == WLAN_GET_PARAM) {
} else {
}
} else if (cmd == WLAN_SET_PARAM) {
}
pcan_p->pcan_usewep = 0;
}
} else {
return (EINVAL);
}
for (i = 0; i < (outfp->wldp_length); i++)
return (iret);
}
static int
{
char *buf;
int iret;
struct an_ltv_wepkey wepkey;
"memory(%d)\n", MAX_BUF_LEN));
return (ENOMEM);
}
if (cmd == WLAN_GET_PARAM) {
} else if (cmd == WLAN_SET_PARAM) {
if (ret > 3) {
return (EINVAL);
}
} else {
return (EINVAL);
}
for (i = 0; i < (outfp->wldp_length); i++)
return (iret);
}
/*ARGSUSED*/
static int
{
uint16_t i;
char *buf;
int iret;
"memory(%d)\n", MAX_BUF_LEN));
return (ENOMEM);
}
for (i = 0; i < (outfp->wldp_length); i++)
return (iret);
}
static int
{
int iret;
char *buf;
struct an_ltv_status *status_p;
"memory(%d)\n", MAX_BUF_LEN));
return (ENOMEM);
}
if (cmd == WLAN_GET_PARAM) {
goto done;
}
/*
* we reflect the value to 1-15 as rssi
*/
} else if (cmd == WLAN_SET_PARAM) {
} else {
return (EINVAL);
}
done:
for (i = 0; i < (outfp->wldp_length); i++)
return (iret);
}
/*ARGSUSED*/
static int
{
uint16_t i;
int iret;
char *buf;
"memory(%d)\n", MAX_BUF_LEN));
return (ENOMEM);
}
if (cmd == WLAN_GET_PARAM) {
} else if (cmd == WLAN_SET_PARAM) {
} else {
return (EINVAL);
}
for (i = 0; i < (outfp->wldp_length); i++)
return (iret);
}
static int
{
uint16_t i;
char *buf;
int iret;
struct an_ltv_wepkey *wepkey_p;
"memory(%d)\n", MAX_BUF_LEN));
return (ENOMEM);
}
if (cmd == WLAN_GET_PARAM) {
sizeof (wl_wep_key_tab_t);
} else if (cmd == WLAN_SET_PARAM) {
for (i = 0; i < MAX_NWEPKEYS; i++) {
}
}
} else {
return (EINVAL);
}
for (i = 0; i < (outfp->wldp_length); i++)
return (iret);
}
static void
pcan_connect_timeout(void *arg)
{
goto done;
goto done;
done:
if (ret)
}
static int
{
int ret = WL_SUCCESS;
int connect = 0;
return (PCAN_FAIL);
}
case WL_ESSID:
connect = 1;
break;
case WL_BSSID:
connect = 1;
break;
case WL_ESS_LIST:
break;
case WL_LINKSTATUS:
break;
case WL_BSS_TYPE:
connect = 1;
break;
case WL_PHY_CONFIG:
connect = 1;
break;
case WL_DESIRED_RATES:
connect = 1;
break;
case WL_SUPPORTED_RATES:
break;
case WL_POWER_MODE:
break;
case WL_AUTH_MODE:
connect = 1;
break;
case WL_ENCRYPTION:
connect = 1;
break;
case WL_WEP_KEY_ID:
connect = 1;
break;
case WL_CREATE_IBSS:
connect = 1;
break;
case WL_RSSI:
break;
case WL_RADIO:
break;
case WL_WEP_KEY_TAB:
connect = 1;
break;
case WL_SCAN:
if (pcan_p->pcan_connect_timeout_id != 0) {
}
/*
* a trick here.
* since the scan doesn't return too many items due to hardware
* reason, so the current scan result is an accumulation of
* several scans. For the first time or after many of the items
* aged, we scan again if too few items now in the scan table.
*/
break;
case WL_LOAD_DEFAULTS:
ret = (int)WL_HW_ERROR;
break;
}
ret = (int)WL_HW_ERROR;
break;
}
ret = (int)WL_HW_ERROR;
break;
}
break;
case WL_DISASSOCIATE:
if (pcan_p->pcan_connect_timeout_id != 0) {
}
ret = (int)WL_HW_ERROR;
break;
}
ret = (int)WL_HW_ERROR;
break;
}
break;
case WL_REASSOCIATE:
case WL_ASSOCIAT:
if (pcan_p->pcan_connect_timeout_id != 0) {
}
ret = (int)WL_HW_ERROR;
break;
}
ret = (int)WL_HW_ERROR;
break;
}
ret = (int)WL_HW_ERROR;
break;
}
break;
default:
break;
}
if (pcan_p->pcan_connect_timeout_id != 0) {
}
}
return (ret);
}
static void
{
/* sanity check */
return;
}
/* assuming single data block */
}
/* we will overwrite everything */
}
static void
{
switch (cmd) {
default:
return;
case WLAN_GET_PARAM:
break;
case WLAN_SET_PARAM:
case WLAN_COMMAND:
break;
}
/* Check net_config privilege */
if (need_privilege) {
return;
}
}
}