xref: /illumos-gate/usr/src/uts/common/io/zyd/zyd.c (revision 0dc2366f)
1e8da18d8Spengcheng chen - Sun Microsystems - Beijing China /*
2*0dc2366fSVenugopal Iyer  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
3e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * Use is subject to license terms.
4e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  */
5e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
6e8da18d8Spengcheng chen - Sun Microsystems - Beijing China /*
7e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * Copyright (c) 2007 by  Lukas Turek <turek@ksvi.mff.cuni.cz>
8e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * Copyright (c) 2007 by  Jiri Svoboda <jirik.svoboda@seznam.cz>
9e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * Copyright (c) 2007 by  Martin Krulis <martin.krulis@matfyz.cz>
10e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * Copyright (c) 2006 by Damien Bergamini <damien.bergamini@free.fr>
11e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * Copyright (c) 2006 by Florian Stoehr <ich@florian-stoehr.de>
12e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  *
13e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * Permission to use, copy, modify, and distribute this software for any
14e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * purpose with or without fee is hereby granted, provided that the above
15e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * copyright notice and this permission notice appear in all copies.
16e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  *
17e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
18e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
19e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
20e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
21e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
22e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
23e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
24e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  *
25e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  */
26e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
27e8da18d8Spengcheng chen - Sun Microsystems - Beijing China /*
28e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * ZD1211 wLAN driver
29e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * Driver major routines
30e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  */
31e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
32e8da18d8Spengcheng chen - Sun Microsystems - Beijing China #include <sys/byteorder.h>
33e8da18d8Spengcheng chen - Sun Microsystems - Beijing China #include <sys/ddi.h>
34e8da18d8Spengcheng chen - Sun Microsystems - Beijing China #include <sys/sunddi.h>
35e8da18d8Spengcheng chen - Sun Microsystems - Beijing China #include <sys/conf.h>
36e8da18d8Spengcheng chen - Sun Microsystems - Beijing China #include <sys/modctl.h>
37e8da18d8Spengcheng chen - Sun Microsystems - Beijing China #include <sys/mac_provider.h>
38e8da18d8Spengcheng chen - Sun Microsystems - Beijing China #include <sys/mac_wifi.h>
39e8da18d8Spengcheng chen - Sun Microsystems - Beijing China #include <sys/strsun.h>
40e8da18d8Spengcheng chen - Sun Microsystems - Beijing China #include <sys/ksynch.h>
41e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
42e8da18d8Spengcheng chen - Sun Microsystems - Beijing China #include "zyd.h"
43e8da18d8Spengcheng chen - Sun Microsystems - Beijing China #include "zyd_reg.h"
44e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
45e8da18d8Spengcheng chen - Sun Microsystems - Beijing China static int zyd_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
46e8da18d8Spengcheng chen - Sun Microsystems - Beijing China static int zyd_detach(dev_info_t *dip, ddi_detach_cmd_t cmd);
47e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
48e8da18d8Spengcheng chen - Sun Microsystems - Beijing China static int zyd_m_stat(void *arg, uint_t stat, uint64_t *val);
49e8da18d8Spengcheng chen - Sun Microsystems - Beijing China static int zyd_m_start(void *arg);
50e8da18d8Spengcheng chen - Sun Microsystems - Beijing China static void zyd_m_stop(void *arg);
51e8da18d8Spengcheng chen - Sun Microsystems - Beijing China static int zyd_m_unicst(void *arg, const uint8_t *macaddr);
52e8da18d8Spengcheng chen - Sun Microsystems - Beijing China static int zyd_m_multicst(void *arg, boolean_t add, const uint8_t *m);
53e8da18d8Spengcheng chen - Sun Microsystems - Beijing China static int zyd_m_promisc(void *arg, boolean_t on);
54e8da18d8Spengcheng chen - Sun Microsystems - Beijing China static void zyd_m_ioctl(void *arg, queue_t *wq, mblk_t *mp);
55e8da18d8Spengcheng chen - Sun Microsystems - Beijing China static mblk_t *zyd_m_tx(void *arg, mblk_t *mp);
56e8da18d8Spengcheng chen - Sun Microsystems - Beijing China static int zyd_m_getprop(void *arg, const char *pr_name,
57*0dc2366fSVenugopal Iyer     mac_prop_id_t wldp_pr_num, uint_t wldp_length, void *wldp_buf);
58*0dc2366fSVenugopal Iyer static void zyd_m_propinfo(void *arg, const char *pr_name,
59*0dc2366fSVenugopal Iyer     mac_prop_id_t wldp_pr_num, mac_prop_info_handle_t mph);
60e8da18d8Spengcheng chen - Sun Microsystems - Beijing China static int zyd_m_setprop(void *arg, const char *pr_name,
61e8da18d8Spengcheng chen - Sun Microsystems - Beijing China     mac_prop_id_t wldp_pr_num, uint_t wldp_length, const void *wldp_buf);
62e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
63e8da18d8Spengcheng chen - Sun Microsystems - Beijing China static int zyd_newstate(struct ieee80211com *ic,
64e8da18d8Spengcheng chen - Sun Microsystems - Beijing China     enum ieee80211_state state, int arg);
65e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
66e8da18d8Spengcheng chen - Sun Microsystems - Beijing China /* Driver identification */
67e8da18d8Spengcheng chen - Sun Microsystems - Beijing China static char zyd_ident[] = ZYD_DRV_DESC " " ZYD_DRV_REV;
68e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
69e8da18d8Spengcheng chen - Sun Microsystems - Beijing China /* Global state pointer for managing per-device soft states */
70e8da18d8Spengcheng chen - Sun Microsystems - Beijing China void *zyd_ssp;
71e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
72e8da18d8Spengcheng chen - Sun Microsystems - Beijing China /*
73e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * Mac Call Back entries
74e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  */
75e8da18d8Spengcheng chen - Sun Microsystems - Beijing China static mac_callbacks_t zyd_m_callbacks = {
76*0dc2366fSVenugopal Iyer 	MC_IOCTL | MC_SETPROP | MC_GETPROP | MC_PROPINFO,
77e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	zyd_m_stat,		/* Get the value of a statistic */
78e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	zyd_m_start,		/* Start the device */
79e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	zyd_m_stop,		/* Stop the device */
80e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	zyd_m_promisc,		/* Enable or disable promiscuous mode */
81e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	zyd_m_multicst,		/* Enable or disable a multicast addr */
82e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	zyd_m_unicst,		/* Set the unicast MAC address */
83e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	zyd_m_tx,		/* Transmit a packet */
84*0dc2366fSVenugopal Iyer 	NULL,
85e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	zyd_m_ioctl,		/* Process an unknown ioctl */
86e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	NULL,			/* mc_getcapab */
87e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	NULL,
88e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	NULL,
89e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	zyd_m_setprop,
90*0dc2366fSVenugopal Iyer 	zyd_m_getprop,
91*0dc2366fSVenugopal Iyer 	zyd_m_propinfo
92e8da18d8Spengcheng chen - Sun Microsystems - Beijing China };
93e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
94e8da18d8Spengcheng chen - Sun Microsystems - Beijing China /*
95e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  *  Module Loading Data & Entry Points
96e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  */
97e8da18d8Spengcheng chen - Sun Microsystems - Beijing China DDI_DEFINE_STREAM_OPS(zyd_devops,	/* name */
98e8da18d8Spengcheng chen - Sun Microsystems - Beijing China     nulldev,			/* identify */
99e8da18d8Spengcheng chen - Sun Microsystems - Beijing China     nulldev,			/* probe */
100e8da18d8Spengcheng chen - Sun Microsystems - Beijing China     zyd_attach,			/* attach */
101e8da18d8Spengcheng chen - Sun Microsystems - Beijing China     zyd_detach,			/* detach */
102e8da18d8Spengcheng chen - Sun Microsystems - Beijing China     nodev,			/* reset */
103e8da18d8Spengcheng chen - Sun Microsystems - Beijing China     NULL,			/* getinfo */
104e8da18d8Spengcheng chen - Sun Microsystems - Beijing China     D_MP,			/* flag */
105e8da18d8Spengcheng chen - Sun Microsystems - Beijing China     NULL,			/* stream_tab */
106e8da18d8Spengcheng chen - Sun Microsystems - Beijing China     ddi_quiesce_not_needed	/* quiesce */
107e8da18d8Spengcheng chen - Sun Microsystems - Beijing China );
108e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
109e8da18d8Spengcheng chen - Sun Microsystems - Beijing China static struct modldrv zyd_modldrv = {
110e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	&mod_driverops,		/* drv_modops */
111e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	zyd_ident,		/* drv_linkinfo */
112e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	&zyd_devops		/* drv_dev_ops */
113e8da18d8Spengcheng chen - Sun Microsystems - Beijing China };
114e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
115e8da18d8Spengcheng chen - Sun Microsystems - Beijing China static struct modlinkage zyd_ml = {
116e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	MODREV_1,		/* ml_rev */
117e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	{&zyd_modldrv, NULL}	/* ml_linkage */
118e8da18d8Spengcheng chen - Sun Microsystems - Beijing China };
119e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
120e8da18d8Spengcheng chen - Sun Microsystems - Beijing China /*
121e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * Wireless-specific structures
122e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  */
123e8da18d8Spengcheng chen - Sun Microsystems - Beijing China static const struct ieee80211_rateset zyd_rateset_11b = {
124e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	4, {2, 4, 11, 22}	/* units are 0.5Mbit! */
125e8da18d8Spengcheng chen - Sun Microsystems - Beijing China };
126e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
127e8da18d8Spengcheng chen - Sun Microsystems - Beijing China static const struct ieee80211_rateset zyd_rateset_11g = {
128e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	12, {2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108}
129e8da18d8Spengcheng chen - Sun Microsystems - Beijing China };
130e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
131e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
132e8da18d8Spengcheng chen - Sun Microsystems - Beijing China #ifdef DEBUG
133e8da18d8Spengcheng chen - Sun Microsystems - Beijing China uint32_t zyd_dbg_flags;
134e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
135e8da18d8Spengcheng chen - Sun Microsystems - Beijing China void
zyd_dbg(uint32_t dbg_mask,const int8_t * fmt,...)136e8da18d8Spengcheng chen - Sun Microsystems - Beijing China zyd_dbg(uint32_t dbg_mask, const int8_t *fmt, ...)
137e8da18d8Spengcheng chen - Sun Microsystems - Beijing China {
138e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	va_list args;
139e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
140e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (dbg_mask & zyd_dbg_flags) {
141e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		va_start(args, fmt);
142e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		vcmn_err(CE_CONT, fmt, args);
143e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		va_end(args);
144e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
145e8da18d8Spengcheng chen - Sun Microsystems - Beijing China }
146e8da18d8Spengcheng chen - Sun Microsystems - Beijing China #endif
147e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
148e8da18d8Spengcheng chen - Sun Microsystems - Beijing China void
zyd_warn(const int8_t * fmt,...)149e8da18d8Spengcheng chen - Sun Microsystems - Beijing China zyd_warn(const int8_t *fmt, ...)
150e8da18d8Spengcheng chen - Sun Microsystems - Beijing China {
151e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	va_list args;
152e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
153e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	va_start(args, fmt);
154e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	vcmn_err(CE_WARN, fmt, args);
155e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	va_end(args);
156e8da18d8Spengcheng chen - Sun Microsystems - Beijing China }
157e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
158e8da18d8Spengcheng chen - Sun Microsystems - Beijing China /*
159e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * Internal functions
160e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  */
161e8da18d8Spengcheng chen - Sun Microsystems - Beijing China static uint8_t
zyd_plcp_signal(uint16_t rate)162e8da18d8Spengcheng chen - Sun Microsystems - Beijing China zyd_plcp_signal(uint16_t rate)
163e8da18d8Spengcheng chen - Sun Microsystems - Beijing China {
164e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	switch (rate) {
165e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		/* CCK rates (returned values are device-dependent) */
166e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	case 2:
167e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		return (0x0);
168e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	case 4:
169e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		return (0x1);
170e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	case 11:
171e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		return (0x2);
172e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	case 22:
173e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		return (0x3);
174e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
175e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		/* OFDM rates (cf IEEE Std 802.11a-1999, pp. 14 Table 80) */
176e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	case 12:
177e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		return (0xb);
178e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	case 18:
179e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		return (0xf);
180e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	case 24:
181e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		return (0xa);
182e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	case 36:
183e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		return (0xe);
184e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	case 48:
185e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		return (0x9);
186e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	case 72:
187e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		return (0xd);
188e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	case 96:
189e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		return (0x8);
190e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	case 108:
191e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		return (0xc);
192e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
193e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		/* unsupported rates (should not get there) */
194e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	default:
195e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		return (0xff);
196e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
197e8da18d8Spengcheng chen - Sun Microsystems - Beijing China }
198e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
199e8da18d8Spengcheng chen - Sun Microsystems - Beijing China /*
200e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * Timeout function for scanning.
201e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  *
202e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * Called at the end of each scanning round.
203e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  */
204e8da18d8Spengcheng chen - Sun Microsystems - Beijing China static void
zyd_next_scan(void * arg)205e8da18d8Spengcheng chen - Sun Microsystems - Beijing China zyd_next_scan(void *arg)
206e8da18d8Spengcheng chen - Sun Microsystems - Beijing China {
207e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	struct zyd_softc *sc = arg;
208e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	struct ieee80211com *ic = &sc->ic;
209e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
210e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	ZYD_DEBUG((ZYD_DBG_SCAN, "scan timer: fired\n"));
211e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
212e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (ic->ic_state == IEEE80211_S_SCAN) {
213e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		ieee80211_next_scan(ic);
214e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	} else {
215e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		ZYD_DEBUG((ZYD_DBG_SCAN, "scan timer: no work\n"));
216e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
217e8da18d8Spengcheng chen - Sun Microsystems - Beijing China }
218e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
219e8da18d8Spengcheng chen - Sun Microsystems - Beijing China /*
220e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * Extract a 802.11 frame from the received packet and forward it to net80211.
221e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  */
222e8da18d8Spengcheng chen - Sun Microsystems - Beijing China void
zyd_receive(struct zyd_softc * sc,const uint8_t * buf,uint16_t len)223e8da18d8Spengcheng chen - Sun Microsystems - Beijing China zyd_receive(struct zyd_softc *sc, const uint8_t *buf, uint16_t len)
224e8da18d8Spengcheng chen - Sun Microsystems - Beijing China {
225e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	const struct zyd_rx_stat *stat;
226e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	struct ieee80211com *ic = &sc->ic;
227e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	struct ieee80211_frame *wh;
228e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	struct ieee80211_node *in;
229e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	int rlen;		/* Actual frame length */
230e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	uint8_t rssi;
231e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	mblk_t *m;
232e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
233e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (len < ZYD_MIN_FRAGSZ) {
234e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		/* Packet is too short, silently drop it */
235e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		sc->rx_err++;
236e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		return;
237e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
238e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
239e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	stat = (const struct zyd_rx_stat *)
240e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	    (buf + len - sizeof (struct zyd_rx_stat));
241e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (stat->flags & ZYD_RX_ERROR) {
242e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		/* Frame is corrupted, silently drop it */
243e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		sc->rx_err++;
244e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		return;
245e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
246e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
247e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	/* compute actual frame length */
248e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	rlen = len - sizeof (struct zyd_plcphdr) -
249e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	    sizeof (struct zyd_rx_stat) - IEEE80211_CRC_LEN;
250e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
251e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	m = allocb(rlen, BPRI_MED);
252e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (m == NULL) {
253e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		sc->rx_nobuf++;
254e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		return;
255e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
256e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
257e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	/* Copy frame to new buffer */
258e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	bcopy(buf + sizeof (struct zyd_plcphdr), m->b_wptr, rlen);
259e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	m->b_wptr += rlen;
260e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
261e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	/* Send frame to net80211 stack */
262e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	wh = (struct ieee80211_frame *)m->b_rptr;
263e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	in = ieee80211_find_rxnode(ic, wh);
264e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	rssi = (stat->rssi < 25) ? 230 : (255 - stat->rssi) / 2;
265e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
266e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	(void) ieee80211_input(ic, m, in, (int32_t)rssi, 0);
267e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
268e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	ieee80211_free_node(in);
269e8da18d8Spengcheng chen - Sun Microsystems - Beijing China }
270e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
271e8da18d8Spengcheng chen - Sun Microsystems - Beijing China /*
272e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * xxx_send callback for net80211.
273e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  *
274e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * Transmit a 802.11 frame.
275e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  *
276e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * Constructs a packet from zyd_tx_header and 802.11 frame data
277e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * and sends it to the chip.
278e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  */
279e8da18d8Spengcheng chen - Sun Microsystems - Beijing China /*ARGSUSED*/
280e8da18d8Spengcheng chen - Sun Microsystems - Beijing China static int
zyd_send(ieee80211com_t * ic,mblk_t * mp,uint8_t type)281e8da18d8Spengcheng chen - Sun Microsystems - Beijing China zyd_send(ieee80211com_t *ic, mblk_t *mp, uint8_t type)
282e8da18d8Spengcheng chen - Sun Microsystems - Beijing China {
283e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	struct zyd_softc *sc = ZYD_IC_TO_SOFTC(ic);
284e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	struct zyd_tx_header *buf_hdr;
285e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	struct ieee80211_frame *wh;
286e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	struct ieee80211_node *in;
287e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	struct ieee80211_key *k;
288e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	mblk_t *m, *m0;
289e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	int len, off, mblen;
290e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	uint16_t frame_size, additional_size, rate;
291e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	uint8_t service;
292e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	int res;
293e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
294e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	ASSERT(mp->b_next == NULL);
295e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
296e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	/* device not ready, drop all frames */
297e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (!sc->usb.connected || sc->suspended || !sc->running) {
298e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		freemsg(mp);
299e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		if (type == IEEE80211_FC0_TYPE_DATA)
300e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 			return (DDI_SUCCESS);
301e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		else
302e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 			return (DDI_FAILURE);
303e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
304e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
305e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	/* device queue overrun */
306e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (sc->tx_queued >= ZYD_TX_LIST_COUNT) {
307e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		/* drop management frames */
308e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		if (type != IEEE80211_FC0_TYPE_DATA) {
309e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 			freemsg(mp);
310e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		} else {
311e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 			(void) zyd_serial_enter(sc, ZYD_NO_SIG);
312e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 			sc->resched = B_TRUE;
313e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 			zyd_serial_exit(sc);
314e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		}
315e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		return (DDI_FAILURE);
316e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
317e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
318e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	m = allocb(msgdsize(mp) + sizeof (struct zyd_tx_header) + 32,
319e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	    BPRI_MED);
320e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (m == NULL) {
321e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		sc->tx_nobuf++;
322e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		(void) zyd_serial_enter(sc, ZYD_NO_SIG);
323e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		sc->resched = B_TRUE;
324e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		zyd_serial_exit(sc);
325e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		return (DDI_FAILURE);
326e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
327e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	m->b_rptr += sizeof (struct zyd_tx_header);
328e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	m->b_wptr = m->b_rptr;
329e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
330e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	for (off = 0, m0 = mp; m0 != NULL; m0 = m0->b_cont) {
331e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		mblen = MBLKL(m0);
332e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		(void) memcpy(m->b_rptr + off, m0->b_rptr, mblen);
333e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		off += mblen;
334e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
335e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	m->b_wptr += off;
336e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
337e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	wh = (struct ieee80211_frame *)m->b_rptr;
338e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	in = ieee80211_find_txnode(ic, wh->i_addr1);
339e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
340e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (in == NULL) {
341e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		freemsg(m);
342e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		sc->tx_err++;
343e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		freemsg(mp);
344e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		return (DDI_SUCCESS);
345e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
346e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	in->in_inact = 0;
347e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
348e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (type == IEEE80211_FC0_TYPE_DATA)
349e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		(void) ieee80211_encap(ic, m, in);
350e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
351e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
352e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		k = ieee80211_crypto_encap(ic, m);
353e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		if (k == NULL) {
354e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 			sc->tx_err++;
355e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 			ieee80211_free_node(in);
356e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 			freemsg(m);
357e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 			freemsg(mp);
358e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 			return (DDI_SUCCESS);
359e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		}
360e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		/* packet header may have moved, reset our local pointer */
361e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		wh = (struct ieee80211_frame *)m->b_rptr;
362e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
363e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
364e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	/*
365e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	 * pickup a rate. May need work to make adaptive - at present,
366e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	 * picks best rate for mode.
367e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	 */
368e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (type == IEEE80211_FC0_TYPE_MGT) {
369e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		/* mgmt frames are sent at 1M */
370e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		rate = (uint16_t)in->in_rates.ir_rates[0];
371e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	} else if (ic->ic_fixed_rate != IEEE80211_FIXED_RATE_NONE) {
372e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		rate = (uint16_t)ic->ic_sup_rates[ic->ic_curmode].
373e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		    ir_rates[ic->ic_fixed_rate];
374e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	} else {
375e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		rate = (uint16_t)ic->ic_sup_rates[ic->ic_curmode].
376e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		    ir_rates[in->in_txrate];
377e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
378e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	rate &= IEEE80211_RATE_VAL;
379e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (rate == 0)		/* should not happen */
380e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		rate = 2;
381e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
382e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	/* Get total length of frame */
383e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	len = msgsize(m);
384e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
385e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	m->b_rptr -= sizeof (struct zyd_tx_header);
386e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	buf_hdr = (struct zyd_tx_header *)m->b_rptr;
387e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
388e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	frame_size = (uint16_t)len + 4;	/* include CRC32 */
389e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	buf_hdr->frame_size = LE_16(frame_size);
390e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
391e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	/*
392e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	 * Compute "packet size". What the 10 stands for,
393e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	 * nobody knows.
394e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	 */
395e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	additional_size = sizeof (struct zyd_tx_header) + 10;
396e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (sc->mac_rev == ZYD_ZD1211)
397e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		buf_hdr->packet_size = LE_16(frame_size + additional_size);
398e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	else
399e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		buf_hdr->packet_size = LE_16(additional_size);
400e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
401e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	buf_hdr->rate_mod_flags = LE_8(zyd_plcp_signal(rate));
402e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	buf_hdr->type_flags = LE_8(ZYD_TX_FLAG_BACKOFF);
403e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
404e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		/* multicast frames are not sent at OFDM rates in 802.11b/g */
405e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		if (frame_size > ic->ic_rtsthreshold) {
406e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 			buf_hdr->type_flags |= ZYD_TX_FLAG_RTS;
407e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		} else if (ZYD_RATE_IS_OFDM(rate) &&
408e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		    (ic->ic_flags & IEEE80211_F_USEPROT)) {
409e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 			if (ic->ic_protmode == IEEE80211_PROT_CTSONLY)
410e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 				buf_hdr->type_flags |=
411e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 				    ZYD_TX_FLAG_CTS_TO_SELF;
412e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 			else if (ic->ic_protmode == IEEE80211_PROT_RTSCTS)
413e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 				buf_hdr->type_flags |= ZYD_TX_FLAG_RTS;
414e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		}
415e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	} else
416e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		buf_hdr->type_flags |= ZYD_TX_FLAG_MULTICAST;
417e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
418e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if ((type == IEEE80211_FC0_TYPE_CTL) &&
419e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	    (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK)
420e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	    == IEEE80211_FC0_SUBTYPE_PS_POLL)
421e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		buf_hdr->type_flags |= ZYD_TX_FLAG_TYPE(ZYD_TX_TYPE_PS_POLL);
422e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
423e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (ZYD_RATE_IS_OFDM(rate)) {
424e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		buf_hdr->rate_mod_flags |= ZYD_TX_RMF_OFDM;
425e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		if (ic->ic_curmode == IEEE80211_MODE_11A)
426e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 			buf_hdr->rate_mod_flags |= ZYD_TX_RMF_5GHZ;
427e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	} else if (rate != 2 && (ic->ic_flags & IEEE80211_F_SHPREAMBLE))
428e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		buf_hdr->rate_mod_flags |= ZYD_TX_RMF_SH_PREAMBLE;
429e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
430e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	/*
431e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	 * Compute frame duration and length-extension service flag.
432e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	 */
433e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	service = 0x00;
434e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
435e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	buf_hdr->frame_duration = LE_16((16 * frame_size + rate - 1) / rate);
436e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	buf_hdr->service = service;
437e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	buf_hdr->next_frame_duration = LE_16(0);
438e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
439e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (rate == 22) {
440e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		const int remainder = (16 * frame_size) % 22;
441e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		if (remainder != 0 && remainder < 7)
442e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 			buf_hdr->service |= ZYD_TX_SERVICE_LENGTH_EXTENSION;
443e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
444e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
445e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	res = zyd_usb_send_packet(&sc->usb, m);
446e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (res != ZYD_SUCCESS) {
447e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		sc->tx_err++;
448e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	} else {
449e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		(void) zyd_serial_enter(sc, ZYD_NO_SIG);
450e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		sc->tx_queued++;
451e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		zyd_serial_exit(sc);
452e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		freemsg(mp);
453e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		ic->ic_stats.is_tx_frags++;
454e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		ic->ic_stats.is_tx_bytes += len;
455e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
456e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
457e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	ieee80211_free_node(in);
458e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
459e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	return (DDI_SUCCESS);
460e8da18d8Spengcheng chen - Sun Microsystems - Beijing China }
461e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
462e8da18d8Spengcheng chen - Sun Microsystems - Beijing China /*
463e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * Register with the MAC layer.
464e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  */
465e8da18d8Spengcheng chen - Sun Microsystems - Beijing China static zyd_res
zyd_mac_init(struct zyd_softc * sc)466e8da18d8Spengcheng chen - Sun Microsystems - Beijing China zyd_mac_init(struct zyd_softc *sc)
467e8da18d8Spengcheng chen - Sun Microsystems - Beijing China {
468e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	struct ieee80211com *ic = &sc->ic;
469e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	mac_register_t *macp;
470e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	wifi_data_t wd = { 0 };
471e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	int err;
472e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
473e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	/*
474e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	 * Initialize mac structure
475e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	 */
476e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	macp = mac_alloc(MAC_VERSION);
477e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (macp == NULL) {
478e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		ZYD_WARN("failed to allocate MAC structure\n");
479e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		return (ZYD_FAILURE);
480e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
481e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
482e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	/*
483e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	 * Initialize pointer to device specific functions
484e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	 */
485e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	wd.wd_secalloc = WIFI_SEC_NONE;
486e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	wd.wd_opmode = sc->ic.ic_opmode;
487e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	IEEE80211_ADDR_COPY(wd.wd_bssid, ic->ic_macaddr);
488e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
489e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	macp->m_type_ident = MAC_PLUGIN_IDENT_WIFI;
490e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	macp->m_driver = sc;
491e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	macp->m_dip = sc->dip;
492e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	macp->m_src_addr = ic->ic_macaddr;
493e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	macp->m_callbacks = &zyd_m_callbacks;
494e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	macp->m_min_sdu = 0;
495e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	macp->m_max_sdu = IEEE80211_MTU;
496e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	macp->m_pdata = &wd;
497e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	macp->m_pdata_size = sizeof (wd);
498e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
499e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	/*
500e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	 * Register the macp to mac
501e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	 */
502e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	err = mac_register(macp, &sc->ic.ic_mach);
503e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	mac_free(macp);
504e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
505e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (err != DDI_SUCCESS) {
506e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		ZYD_WARN("failed to register MAC structure\n");
507e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		return (ZYD_FAILURE);
508e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
509e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
510e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	return (ZYD_SUCCESS);
511e8da18d8Spengcheng chen - Sun Microsystems - Beijing China }
512e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
513e8da18d8Spengcheng chen - Sun Microsystems - Beijing China /*
514e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * Register with net80211.
515e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  */
516e8da18d8Spengcheng chen - Sun Microsystems - Beijing China static void
zyd_wifi_init(struct zyd_softc * sc)517e8da18d8Spengcheng chen - Sun Microsystems - Beijing China zyd_wifi_init(struct zyd_softc *sc)
518e8da18d8Spengcheng chen - Sun Microsystems - Beijing China {
519e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	struct ieee80211com *ic = &sc->ic;
520e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	int i;
521e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
522e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	/*
523e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	 * Initialize the WiFi part, which will be used by generic layer
524e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	 */
525e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	ic->ic_phytype = IEEE80211_T_OFDM;
526e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	ic->ic_opmode = IEEE80211_M_STA;
527e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	ic->ic_state = IEEE80211_S_INIT;
528e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	ic->ic_maxrssi = 255;
529e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	ic->ic_xmit = zyd_send;
530e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
531e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	/* set device capabilities */
532e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	ic->ic_caps = IEEE80211_C_TXPMGT |	/* tx power management */
533e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	    IEEE80211_C_SHPREAMBLE |		/* short preamble supported */
534e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	    IEEE80211_C_SHSLOT | IEEE80211_C_WPA;	/* Support WPA/WPA2 */
535e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
536e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	/* Copy MAC address */
537e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	IEEE80211_ADDR_COPY(ic->ic_macaddr, sc->macaddr);
538e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
539e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	/*
540e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	 * set supported .11b and .11g rates
541e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	 */
542e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	ic->ic_sup_rates[IEEE80211_MODE_11B] = zyd_rateset_11b;
543e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	ic->ic_sup_rates[IEEE80211_MODE_11G] = zyd_rateset_11g;
544e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
545e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	/*
546e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	 * set supported .11b and .11g channels(1 through 14)
547e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	 */
548e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	for (i = 1; i <= 14; i++) {
549e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		ic->ic_sup_channels[i].ich_freq =
550e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		    ieee80211_ieee2mhz(i, IEEE80211_CHAN_2GHZ);
551e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		ic->ic_sup_channels[i].ich_flags =
552e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		    IEEE80211_CHAN_CCK | IEEE80211_CHAN_OFDM |
553e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		    IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ;
554e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
555e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
556e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	/*
557e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	 * Init generic layer (it cannot fail)
558e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	 */
559e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	ieee80211_attach(ic);
560e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
561e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	/* register WPA door */
562e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	ieee80211_register_door(ic, ddi_driver_name(sc->dip),
563e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	    ddi_get_instance(sc->dip));
564e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
565e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	/* Must be after attach! */
566e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	sc->newstate = ic->ic_newstate;
567e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	ic->ic_newstate = zyd_newstate;
568e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
569e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	ieee80211_media_init(ic);
570e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	ic->ic_def_txkey = 0;
571e8da18d8Spengcheng chen - Sun Microsystems - Beijing China }
572e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
573e8da18d8Spengcheng chen - Sun Microsystems - Beijing China /*
574e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * Device operations
575e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  */
576e8da18d8Spengcheng chen - Sun Microsystems - Beijing China /*
577e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * Binding the driver to a device.
578e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  *
579e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * Concurrency: Until zyd_attach() returns with success,
580e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * the only other entry point that can be executed is getinfo().
581e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * Thus no locking here yet.
582e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  */
583e8da18d8Spengcheng chen - Sun Microsystems - Beijing China static int
zyd_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)584e8da18d8Spengcheng chen - Sun Microsystems - Beijing China zyd_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
585e8da18d8Spengcheng chen - Sun Microsystems - Beijing China {
586e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	struct zyd_softc *sc;
587e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	char strbuf[32];
588e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	int instance;
589e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	int err;
590e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
591e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	switch (cmd) {
592e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	case DDI_ATTACH:
593e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		break;
594e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
595e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	case DDI_RESUME:
596e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		sc = ddi_get_soft_state(zyd_ssp, ddi_get_instance(dip));
597e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		ASSERT(sc != NULL);
598e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
599e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		(void) zyd_resume(sc);
600e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		return (DDI_SUCCESS);
601e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
602e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	default:
603e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		return (DDI_FAILURE);
604e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
605e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
606e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	instance = ddi_get_instance(dip);
607e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	err = ddi_soft_state_zalloc(zyd_ssp, instance);
608e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
609e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (err != DDI_SUCCESS) {
610e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		ZYD_WARN("failed to allocate soft state\n");
611e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		return (DDI_FAILURE);
612e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
613e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
614e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	sc = ddi_get_soft_state(zyd_ssp, instance);
615e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	sc->dip = dip;
616e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	sc->timeout_id = 0;
617e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
618e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (zyd_usb_init(sc) != ZYD_SUCCESS) {
619e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		ddi_soft_state_free(zyd_ssp, instance);
620e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		return (DDI_FAILURE);
621e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
622e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
623e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (zyd_hw_init(sc) != ZYD_SUCCESS) {
624e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		zyd_usb_deinit(sc);
625e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		ddi_soft_state_free(zyd_ssp, instance);
626e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		return (DDI_FAILURE);
627e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
628e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
629e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	zyd_wifi_init(sc);
630e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
631e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (zyd_mac_init(sc) != DDI_SUCCESS) {
632e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		ieee80211_detach(&sc->ic);
633e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		zyd_usb_deinit(sc);
634e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		ddi_soft_state_free(zyd_ssp, instance);
635e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		return (DDI_FAILURE);
636e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
637e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
638e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	/*
639e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	 * Create minor node of type DDI_NT_NET_WIFI
640e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	 */
641e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	(void) snprintf(strbuf, sizeof (strbuf), ZYD_DRV_NAME"%d", instance);
642e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	err = ddi_create_minor_node(dip, strbuf, S_IFCHR,
643e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	    instance + 1, DDI_NT_NET_WIFI, 0);
644e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (err != DDI_SUCCESS)
645e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		ZYD_WARN("failed to create minor node\n");
646e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
647e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	/* initialize locking */
648e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	zyd_serial_init(sc);
649e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
650e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	return (DDI_SUCCESS);
651e8da18d8Spengcheng chen - Sun Microsystems - Beijing China }
652e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
653e8da18d8Spengcheng chen - Sun Microsystems - Beijing China /*
654e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * Detach the driver from a device.
655e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  *
656e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * Concurrency: Will be called only after a successful attach
657e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * (and not concurrently).
658e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  */
659e8da18d8Spengcheng chen - Sun Microsystems - Beijing China static int
zyd_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)660e8da18d8Spengcheng chen - Sun Microsystems - Beijing China zyd_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
661e8da18d8Spengcheng chen - Sun Microsystems - Beijing China {
662e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	struct zyd_softc *sc = NULL;
663e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
664e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	switch (cmd) {
665e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	case DDI_DETACH:
666e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		break;
667e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
668e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	case DDI_SUSPEND:
669e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		sc = ddi_get_soft_state(zyd_ssp, ddi_get_instance(dip));
670e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		ASSERT(sc != NULL);
671e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
672e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		return (zyd_suspend(sc));
673e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
674e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	default:
675e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		return (DDI_FAILURE);
676e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
677e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
678e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	sc = ddi_get_soft_state(zyd_ssp, ddi_get_instance(dip));
679e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	ASSERT(sc != NULL);
680e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
681e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (mac_disable(sc->ic.ic_mach) != 0)
682e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		return (DDI_FAILURE);
683e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	/*
684e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	 * Unregister from the MAC layer subsystem
685e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	 */
686e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	(void) mac_unregister(sc->ic.ic_mach);
687e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
688e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	/*
689e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	 * Detach ieee80211
690e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	 */
691e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	ieee80211_detach(&sc->ic);
692e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
693e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	zyd_hw_deinit(sc);
694e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	zyd_usb_deinit(sc);
695e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
696e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	/* At this point it should be safe to release & destroy the locks */
697e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	zyd_serial_deinit(sc);
698e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
699e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	ddi_remove_minor_node(dip, NULL);
700e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	ddi_soft_state_free(zyd_ssp, ddi_get_instance(dip));
701e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	return (DDI_SUCCESS);
702e8da18d8Spengcheng chen - Sun Microsystems - Beijing China }
703e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
704e8da18d8Spengcheng chen - Sun Microsystems - Beijing China /*
705e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * Mac Call Back functions
706e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  */
707e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
708e8da18d8Spengcheng chen - Sun Microsystems - Beijing China /*
709e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * Read device statistic information.
710e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  */
711e8da18d8Spengcheng chen - Sun Microsystems - Beijing China static int
zyd_m_stat(void * arg,uint_t stat,uint64_t * val)712e8da18d8Spengcheng chen - Sun Microsystems - Beijing China zyd_m_stat(void *arg, uint_t stat, uint64_t *val)
713e8da18d8Spengcheng chen - Sun Microsystems - Beijing China {
714e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	struct zyd_softc *sc = (struct zyd_softc *)arg;
715e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	ieee80211com_t *ic = &sc->ic;
716e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	ieee80211_node_t *in;
717e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
718e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	switch (stat) {
719e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	case MAC_STAT_IFSPEED:
720e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		if (!sc->usb.connected || sc->suspended || !sc->running)
721e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 			return (ENOTSUP);
722e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		in = ieee80211_ref_node(ic->ic_bss);
723e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		*val = ((ic->ic_fixed_rate == IEEE80211_FIXED_RATE_NONE) ?
724e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		    IEEE80211_RATE(in->in_txrate) :
725e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		    ic->ic_fixed_rate) / 2 * 1000000;
726e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		ieee80211_free_node(in);
727e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		break;
728e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	case MAC_STAT_NOXMTBUF:
729e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		*val = sc->tx_nobuf;
730e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		break;
731e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	case MAC_STAT_NORCVBUF:
732e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		*val = sc->rx_nobuf;
733e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		break;
734e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	case MAC_STAT_IERRORS:
735e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		*val = sc->rx_err;
736e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		break;
737e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	case MAC_STAT_RBYTES:
738e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		*val = ic->ic_stats.is_rx_bytes;
739e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		break;
740e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	case MAC_STAT_IPACKETS:
741e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		*val = ic->ic_stats.is_rx_frags;
742e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		break;
743e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	case MAC_STAT_OBYTES:
744e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		*val = ic->ic_stats.is_tx_bytes;
745e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		break;
746e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	case MAC_STAT_OPACKETS:
747e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		*val = ic->ic_stats.is_tx_frags;
748e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		break;
749e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	case MAC_STAT_OERRORS:
750e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	case WIFI_STAT_TX_FAILED:
751e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		*val = sc->tx_err;
752e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		break;
753e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	case WIFI_STAT_TX_RETRANS:
754e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	case WIFI_STAT_FCS_ERRORS:
755e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	case WIFI_STAT_WEP_ERRORS:
756e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	case WIFI_STAT_TX_FRAGS:
757e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	case WIFI_STAT_MCAST_TX:
758e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	case WIFI_STAT_RTS_SUCCESS:
759e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	case WIFI_STAT_RTS_FAILURE:
760e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	case WIFI_STAT_ACK_FAILURE:
761e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	case WIFI_STAT_RX_FRAGS:
762e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	case WIFI_STAT_MCAST_RX:
763e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	case WIFI_STAT_RX_DUPS:
764e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		return (ieee80211_stat(ic, stat, val));
765e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	default:
766e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		return (ENOTSUP);
767e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
768e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	return (0);
769e8da18d8Spengcheng chen - Sun Microsystems - Beijing China }
770e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
771e8da18d8Spengcheng chen - Sun Microsystems - Beijing China /*
772e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * Start the device.
773e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  *
774e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * Concurrency: Presumably fully concurrent, must lock.
775e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  */
776e8da18d8Spengcheng chen - Sun Microsystems - Beijing China static int
zyd_m_start(void * arg)777e8da18d8Spengcheng chen - Sun Microsystems - Beijing China zyd_m_start(void *arg)
778e8da18d8Spengcheng chen - Sun Microsystems - Beijing China {
779e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	struct zyd_softc *sc = (struct zyd_softc *)arg;
780e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
781e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	(void) zyd_serial_enter(sc, ZYD_NO_SIG);
782e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if ((!sc->usb.connected) || (zyd_hw_start(sc) != ZYD_SUCCESS)) {
783e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		zyd_serial_exit(sc);
784e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		return (DDI_FAILURE);
785e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
786e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	zyd_serial_exit(sc);
787e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
788e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	ieee80211_new_state(&sc->ic, IEEE80211_S_INIT, -1);
789e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	sc->running = B_TRUE;
790e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
791e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	return (DDI_SUCCESS);
792e8da18d8Spengcheng chen - Sun Microsystems - Beijing China }
793e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
794e8da18d8Spengcheng chen - Sun Microsystems - Beijing China /*
795e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * Stop the device.
796e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  */
797e8da18d8Spengcheng chen - Sun Microsystems - Beijing China static void
zyd_m_stop(void * arg)798e8da18d8Spengcheng chen - Sun Microsystems - Beijing China zyd_m_stop(void *arg)
799e8da18d8Spengcheng chen - Sun Microsystems - Beijing China {
800e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	struct zyd_softc *sc = (struct zyd_softc *)arg;
801e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
802e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	sc->running = B_FALSE;
803e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	ieee80211_new_state(&sc->ic, IEEE80211_S_INIT, -1);
804e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
805e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	(void) zyd_serial_enter(sc, ZYD_NO_SIG);
806e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	sc->resched = B_FALSE;
807e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	zyd_hw_stop(sc);
808e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	zyd_serial_exit(sc);
809e8da18d8Spengcheng chen - Sun Microsystems - Beijing China }
810e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
811e8da18d8Spengcheng chen - Sun Microsystems - Beijing China /*
812e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * Change the MAC address of the device.
813e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  */
814e8da18d8Spengcheng chen - Sun Microsystems - Beijing China /*ARGSUSED*/
815e8da18d8Spengcheng chen - Sun Microsystems - Beijing China static int
zyd_m_unicst(void * arg,const uint8_t * macaddr)816e8da18d8Spengcheng chen - Sun Microsystems - Beijing China zyd_m_unicst(void *arg, const uint8_t *macaddr)
817e8da18d8Spengcheng chen - Sun Microsystems - Beijing China {
818e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	return (DDI_FAILURE);
819e8da18d8Spengcheng chen - Sun Microsystems - Beijing China }
820e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
821e8da18d8Spengcheng chen - Sun Microsystems - Beijing China /*
822e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * Enable/disable multicast.
823e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  */
824e8da18d8Spengcheng chen - Sun Microsystems - Beijing China /*ARGSUSED*/
825e8da18d8Spengcheng chen - Sun Microsystems - Beijing China static int
zyd_m_multicst(void * arg,boolean_t add,const uint8_t * m)826e8da18d8Spengcheng chen - Sun Microsystems - Beijing China zyd_m_multicst(void *arg, boolean_t add, const uint8_t *m)
827e8da18d8Spengcheng chen - Sun Microsystems - Beijing China {
828e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	ZYD_DEBUG((ZYD_DBG_GLD, "multicast not implemented\n"));
829e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	return (DDI_SUCCESS);
830e8da18d8Spengcheng chen - Sun Microsystems - Beijing China }
831e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
832e8da18d8Spengcheng chen - Sun Microsystems - Beijing China /*
833e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * Enable/disable promiscuous mode.
834e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  */
835e8da18d8Spengcheng chen - Sun Microsystems - Beijing China /*ARGSUSED*/
836e8da18d8Spengcheng chen - Sun Microsystems - Beijing China static int
zyd_m_promisc(void * arg,boolean_t on)837e8da18d8Spengcheng chen - Sun Microsystems - Beijing China zyd_m_promisc(void *arg, boolean_t on)
838e8da18d8Spengcheng chen - Sun Microsystems - Beijing China {
839e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	ZYD_DEBUG((ZYD_DBG_GLD, "promiscuous not implemented\n"));
840e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	return (DDI_SUCCESS);
841e8da18d8Spengcheng chen - Sun Microsystems - Beijing China }
842e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
843e8da18d8Spengcheng chen - Sun Microsystems - Beijing China /*
844e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * IOCTL request.
845e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  */
846e8da18d8Spengcheng chen - Sun Microsystems - Beijing China static void
zyd_m_ioctl(void * arg,queue_t * wq,mblk_t * mp)847e8da18d8Spengcheng chen - Sun Microsystems - Beijing China zyd_m_ioctl(void *arg, queue_t *wq, mblk_t *mp)
848e8da18d8Spengcheng chen - Sun Microsystems - Beijing China {
849e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	struct zyd_softc *sc = (struct zyd_softc *)arg;
850e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	struct ieee80211com *ic = &sc->ic;
851e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
852e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (!sc->usb.connected || sc->suspended || !sc->running) {
853e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		miocnak(wq, mp, 0, ENXIO);
854e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		return;
855e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
856e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
857e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (ieee80211_ioctl(ic, wq, mp) == ENETRESET) {
858e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		if (sc->running && ic->ic_des_esslen) {
859e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 			zyd_m_stop(sc);
860e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 			if (zyd_m_start(sc) != DDI_SUCCESS)
861e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 				return;
862e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 			ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
863e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		}
864e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
865e8da18d8Spengcheng chen - Sun Microsystems - Beijing China }
866e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
867e8da18d8Spengcheng chen - Sun Microsystems - Beijing China /*
868e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * callback functions for /get/set properties
869e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  */
870e8da18d8Spengcheng chen - Sun Microsystems - Beijing China static int
zyd_m_setprop(void * arg,const char * pr_name,mac_prop_id_t wldp_pr_num,uint_t wldp_length,const void * wldp_buf)871e8da18d8Spengcheng chen - Sun Microsystems - Beijing China zyd_m_setprop(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num,
872e8da18d8Spengcheng chen - Sun Microsystems - Beijing China     uint_t wldp_length, const void *wldp_buf)
873e8da18d8Spengcheng chen - Sun Microsystems - Beijing China {
874e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	struct zyd_softc *sc = (struct zyd_softc *)arg;
875e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	struct ieee80211com *ic = &sc->ic;
876e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	int err;
877e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
878e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (!sc->usb.connected || sc->suspended || !sc->running) {
879e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		return (ENXIO);
880e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
881e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
882e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	err = ieee80211_setprop(ic, pr_name, wldp_pr_num, wldp_length,
883e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	    wldp_buf);
884e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (err == ENETRESET) {
885e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		if (sc->running && ic->ic_des_esslen) {
886e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 			zyd_m_stop(sc);
887e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 			if (zyd_m_start(sc) != DDI_SUCCESS)
888e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 				return (DDI_FAILURE);
889e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 			ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
890e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		}
891e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		err = 0;
892e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
893e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
894e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	return (err);
895e8da18d8Spengcheng chen - Sun Microsystems - Beijing China }
896e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
897e8da18d8Spengcheng chen - Sun Microsystems - Beijing China static int
zyd_m_getprop(void * arg,const char * pr_name,mac_prop_id_t wldp_pr_num,uint_t wldp_length,void * wldp_buf)898e8da18d8Spengcheng chen - Sun Microsystems - Beijing China zyd_m_getprop(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num,
899*0dc2366fSVenugopal Iyer     uint_t wldp_length, void *wldp_buf)
900e8da18d8Spengcheng chen - Sun Microsystems - Beijing China {
901e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	struct zyd_softc *sc = (struct zyd_softc *)arg;
902e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	int err;
903e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
904e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (!sc->usb.connected || sc->suspended || !sc->running) {
905e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		return (DDI_FAILURE);
906e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
907e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
908e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	err = ieee80211_getprop(&sc->ic, pr_name, wldp_pr_num,
909*0dc2366fSVenugopal Iyer 	    wldp_length, wldp_buf);
910e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
911e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	return (err);
912e8da18d8Spengcheng chen - Sun Microsystems - Beijing China }
913e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
914*0dc2366fSVenugopal Iyer static void
zyd_m_propinfo(void * arg,const char * pr_name,mac_prop_id_t wldp_pr_num,mac_prop_info_handle_t mph)915*0dc2366fSVenugopal Iyer zyd_m_propinfo(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num,
916*0dc2366fSVenugopal Iyer     mac_prop_info_handle_t mph)
917*0dc2366fSVenugopal Iyer {
918*0dc2366fSVenugopal Iyer 	struct zyd_softc *sc = (struct zyd_softc *)arg;
919*0dc2366fSVenugopal Iyer 
920*0dc2366fSVenugopal Iyer 	ieee80211_propinfo(&sc->ic, pr_name, wldp_pr_num, mph);
921*0dc2366fSVenugopal Iyer }
922*0dc2366fSVenugopal Iyer 
923e8da18d8Spengcheng chen - Sun Microsystems - Beijing China /*
924e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * Transmit a data frame.
925e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  */
926e8da18d8Spengcheng chen - Sun Microsystems - Beijing China static mblk_t *
zyd_m_tx(void * arg,mblk_t * mp)927e8da18d8Spengcheng chen - Sun Microsystems - Beijing China zyd_m_tx(void *arg, mblk_t *mp)
928e8da18d8Spengcheng chen - Sun Microsystems - Beijing China {
929e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	struct zyd_softc *sc = (struct zyd_softc *)arg;
930e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	struct ieee80211com *ic = &sc->ic;
931e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	mblk_t *next;
932e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
933e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	ASSERT(mp != NULL);
934e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
935e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	/* not associated, drop data frames */
936e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (ic->ic_state != IEEE80211_S_RUN) {
937e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		freemsg(mp);
938e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		return (DDI_SUCCESS);
939e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
940e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
941e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	while (mp != NULL) {
942e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		next = mp->b_next;
943e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		mp->b_next = NULL;
944e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
945e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		if (zyd_send(ic, mp, IEEE80211_FC0_TYPE_DATA) != DDI_SUCCESS) {
946e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 			mp->b_next = next;
947e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 			break;
948e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		}
949e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		mp = next;
950e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
951e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
952e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	return (mp);
953e8da18d8Spengcheng chen - Sun Microsystems - Beijing China }
954e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
955e8da18d8Spengcheng chen - Sun Microsystems - Beijing China /*
956e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * xxx_newstate callback for net80211.
957e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  *
958e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * Called by net80211 whenever the ieee80211 state changes.
959e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  */
960e8da18d8Spengcheng chen - Sun Microsystems - Beijing China static int
zyd_newstate(struct ieee80211com * ic,enum ieee80211_state nstate,int arg)961e8da18d8Spengcheng chen - Sun Microsystems - Beijing China zyd_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
962e8da18d8Spengcheng chen - Sun Microsystems - Beijing China {
963e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	struct zyd_softc *sc = ZYD_IC_TO_SOFTC(ic);
964e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	struct ieee80211_node *in;
965e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	uint_t chan;
966e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
967e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (sc->timeout_id != 0) {
968e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		(void) untimeout(sc->timeout_id);
969e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		sc->timeout_id = 0;
970e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
971e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
972e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (!sc->usb.connected || sc->suspended || !sc->running) {
973e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		return (sc->newstate(ic, nstate, arg));
974e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
975e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
976e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	switch (nstate) {
977e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	case IEEE80211_S_SCAN:
978e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		ZYD_DEBUG((ZYD_DBG_SCAN, "scan timer: starting next\n"));
979e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		sc->timeout_id = timeout(zyd_next_scan, sc,
980e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		    drv_usectohz(ZYD_DWELL_TIME));
981e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		/*FALLTHRU*/
982e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	case IEEE80211_S_AUTH:
983e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	case IEEE80211_S_ASSOC:
984e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	case IEEE80211_S_RUN:
985e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		chan = ieee80211_chan2ieee(ic, ic->ic_curchan);
986e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		if (chan == 0 || chan == IEEE80211_CHAN_ANY) {
987e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 			ZYD_WARN("invalid channel number\n");
988e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 			return (0);
989e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		}
990e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		(void) zyd_serial_enter(sc, ZYD_SER_SIG);
991e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		zyd_hw_set_channel(sc, chan);
992e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		zyd_serial_exit(sc);
993e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
994e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		in = ic->ic_bss;
995e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		in->in_txrate = in->in_rates.ir_nrates - 1;
996e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	default:
997e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		break;
998e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
999e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
1000e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	return (sc->newstate(ic, nstate, arg));
1001e8da18d8Spengcheng chen - Sun Microsystems - Beijing China }
1002e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
1003e8da18d8Spengcheng chen - Sun Microsystems - Beijing China /*
1004e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * USB-safe synchronization.
1005e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * Debugging routines.
1006e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  *
1007e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * Kmutexes should never be held when making calls to USBA
1008e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * or when sleeping. Thus, we implement our own "mutex" on top
1009e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * of kmutexes and kcondvars.
1010e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  *
1011e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * Usage: Any (possibly concurrent) access to the soft state or device must
1012e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * be serialized with a pair of zyd_serial_enter()/zyd_serial_exit().
1013e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  */
1014e8da18d8Spengcheng chen - Sun Microsystems - Beijing China /*
1015e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * Initialize the serialization object.
1016e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  */
1017e8da18d8Spengcheng chen - Sun Microsystems - Beijing China void
zyd_serial_init(struct zyd_softc * sc)1018e8da18d8Spengcheng chen - Sun Microsystems - Beijing China zyd_serial_init(struct zyd_softc *sc)
1019e8da18d8Spengcheng chen - Sun Microsystems - Beijing China {
1020e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	mutex_init(&sc->serial.lock, NULL, MUTEX_DRIVER,
1021e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	    sc->usb.cdata->dev_iblock_cookie);
1022e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	cv_init(&sc->serial.wait, NULL, CV_DRIVER, NULL);
1023e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
1024e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	sc->serial.held = B_FALSE;
1025e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	sc->serial.initialized = B_TRUE;
1026e8da18d8Spengcheng chen - Sun Microsystems - Beijing China }
1027e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
1028e8da18d8Spengcheng chen - Sun Microsystems - Beijing China /*
1029e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * Wait for the serialization object.
1030e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  *
1031e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * If wait_sig is ZYD_SER_SIG, the function may return
1032e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * a signal is received. In this case, the serialization object
1033e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * is not acquired (but the mutex is) and the return value is ZYD_FAILURE.
1034e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  *
1035e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * In any other case the function returns ZYD_SUCCESS and the
1036e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * serialization object is acquired.
1037e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  */
1038e8da18d8Spengcheng chen - Sun Microsystems - Beijing China zyd_res
zyd_serial_enter(struct zyd_softc * sc,boolean_t wait_sig)1039e8da18d8Spengcheng chen - Sun Microsystems - Beijing China zyd_serial_enter(struct zyd_softc *sc, boolean_t wait_sig)
1040e8da18d8Spengcheng chen - Sun Microsystems - Beijing China {
1041e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	zyd_res res;
1042e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
1043e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	mutex_enter(&sc->serial.lock);
1044e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
1045e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	res = ZYD_SUCCESS;
1046e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
1047e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	while (sc->serial.held != B_FALSE) {
1048e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		if (wait_sig == ZYD_SER_SIG) {
1049e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 			res = cv_wait_sig(&sc->serial.wait, &sc->serial.lock);
1050e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		} else {
1051e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 			cv_wait(&sc->serial.wait, &sc->serial.lock);
1052e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		}
1053e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
1054e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	sc->serial.held = B_TRUE;
1055e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
1056e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	mutex_exit(&sc->serial.lock);
1057e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
1058e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	return (res);
1059e8da18d8Spengcheng chen - Sun Microsystems - Beijing China }
1060e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
1061e8da18d8Spengcheng chen - Sun Microsystems - Beijing China /*
1062e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * Release the serialization object.
1063e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  */
1064e8da18d8Spengcheng chen - Sun Microsystems - Beijing China void
zyd_serial_exit(struct zyd_softc * sc)1065e8da18d8Spengcheng chen - Sun Microsystems - Beijing China zyd_serial_exit(struct zyd_softc *sc)
1066e8da18d8Spengcheng chen - Sun Microsystems - Beijing China {
1067e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	mutex_enter(&sc->serial.lock);
1068e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	sc->serial.held = B_FALSE;
1069e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	cv_broadcast(&sc->serial.wait);
1070e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	mutex_exit(&sc->serial.lock);
1071e8da18d8Spengcheng chen - Sun Microsystems - Beijing China }
1072e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
1073e8da18d8Spengcheng chen - Sun Microsystems - Beijing China /*
1074e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * Destroy the serialization object.
1075e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  */
1076e8da18d8Spengcheng chen - Sun Microsystems - Beijing China void
zyd_serial_deinit(struct zyd_softc * sc)1077e8da18d8Spengcheng chen - Sun Microsystems - Beijing China zyd_serial_deinit(struct zyd_softc *sc)
1078e8da18d8Spengcheng chen - Sun Microsystems - Beijing China {
1079e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	cv_destroy(&sc->serial.wait);
1080e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	mutex_destroy(&sc->serial.lock);
1081e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
1082e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	sc->serial.initialized = B_FALSE;
1083e8da18d8Spengcheng chen - Sun Microsystems - Beijing China }
1084e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
1085e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
1086e8da18d8Spengcheng chen - Sun Microsystems - Beijing China /*
1087e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * zyd_cb_lock: a special signal structure that is used for notification
1088e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * that a callback function has been called.
1089e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  */
1090e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
1091e8da18d8Spengcheng chen - Sun Microsystems - Beijing China /* Initializes the zyd_cb_lock structure. */
1092e8da18d8Spengcheng chen - Sun Microsystems - Beijing China void
zyd_cb_lock_init(struct zyd_cb_lock * lock)1093e8da18d8Spengcheng chen - Sun Microsystems - Beijing China zyd_cb_lock_init(struct zyd_cb_lock *lock)
1094e8da18d8Spengcheng chen - Sun Microsystems - Beijing China {
1095e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	ASSERT(lock != NULL);
1096e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	mutex_init(&lock->mutex, NULL, MUTEX_DRIVER, NULL);
1097e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	cv_init(&lock->cv, NULL, CV_DRIVER, NULL);
1098e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	lock->done = B_FALSE;
1099e8da18d8Spengcheng chen - Sun Microsystems - Beijing China }
1100e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
1101e8da18d8Spengcheng chen - Sun Microsystems - Beijing China /* Deinitalizes the zyd_cb_lock structure. */
1102e8da18d8Spengcheng chen - Sun Microsystems - Beijing China void
zyd_cb_lock_destroy(struct zyd_cb_lock * lock)1103e8da18d8Spengcheng chen - Sun Microsystems - Beijing China zyd_cb_lock_destroy(struct zyd_cb_lock *lock)
1104e8da18d8Spengcheng chen - Sun Microsystems - Beijing China {
1105e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	ASSERT(lock != NULL);
1106e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	mutex_destroy(&lock->mutex);
1107e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	cv_destroy(&lock->cv);
1108e8da18d8Spengcheng chen - Sun Microsystems - Beijing China }
1109e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
1110e8da18d8Spengcheng chen - Sun Microsystems - Beijing China /*
1111e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * Wait on lock until someone calls the "signal" function or the timeout
1112e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * expires. Note: timeout is in microseconds.
1113e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  */
1114e8da18d8Spengcheng chen - Sun Microsystems - Beijing China zyd_res
zyd_cb_lock_wait(struct zyd_cb_lock * lock,clock_t timeout)1115e8da18d8Spengcheng chen - Sun Microsystems - Beijing China zyd_cb_lock_wait(struct zyd_cb_lock *lock, clock_t timeout)
1116e8da18d8Spengcheng chen - Sun Microsystems - Beijing China {
1117e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	zyd_res res;
1118e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	clock_t etime;
1119e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	int cv_res;
1120e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
1121e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	ASSERT(lock != NULL);
1122e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
1123e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	mutex_enter(&lock->mutex);
1124e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
1125e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (timeout < 0) {
1126e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		/* no timeout - wait as long as needed */
1127e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		while (lock->done == B_FALSE)
1128e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 			(void) cv_wait(&lock->cv, &lock->mutex);
1129e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	} else {
1130e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		/* wait with timeout (given in usec) */
1131e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		etime = ddi_get_lbolt() + drv_usectohz(timeout);
1132e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		while (lock->done == B_FALSE) {
1133e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 			cv_res =
1134e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 			    cv_timedwait_sig(&lock->cv, &lock->mutex, etime);
1135e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 			if (cv_res <= 0)
1136e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 				break;
1137e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		}
1138e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
1139e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
1140e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	res = (lock->done == B_TRUE) ? ZYD_SUCCESS : ZYD_FAILURE;
1141e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
1142e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	mutex_exit(&lock->mutex);
1143e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
1144e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	return (res);
1145e8da18d8Spengcheng chen - Sun Microsystems - Beijing China }
1146e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
1147e8da18d8Spengcheng chen - Sun Microsystems - Beijing China /* Signal that the job (eg. callback) is done and unblock anyone who waits. */
1148e8da18d8Spengcheng chen - Sun Microsystems - Beijing China void
zyd_cb_lock_signal(struct zyd_cb_lock * lock)1149e8da18d8Spengcheng chen - Sun Microsystems - Beijing China zyd_cb_lock_signal(struct zyd_cb_lock *lock)
1150e8da18d8Spengcheng chen - Sun Microsystems - Beijing China {
1151e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	ASSERT(lock != NULL);
1152e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
1153e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	mutex_enter(&lock->mutex);
1154e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
1155e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	lock->done = B_TRUE;
1156e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	cv_broadcast(&lock->cv);
1157e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
1158e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	mutex_exit(&lock->mutex);
1159e8da18d8Spengcheng chen - Sun Microsystems - Beijing China }
1160e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
1161e8da18d8Spengcheng chen - Sun Microsystems - Beijing China /*
1162e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * Loadable module configuration entry points
1163e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  */
1164e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
1165e8da18d8Spengcheng chen - Sun Microsystems - Beijing China /*
1166e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * _init module entry point.
1167e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  *
1168e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * Called when the module is being loaded into memory.
1169e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  */
1170e8da18d8Spengcheng chen - Sun Microsystems - Beijing China int
_init(void)1171e8da18d8Spengcheng chen - Sun Microsystems - Beijing China _init(void)
1172e8da18d8Spengcheng chen - Sun Microsystems - Beijing China {
1173e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	int err;
1174e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
1175e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	err = ddi_soft_state_init(&zyd_ssp, sizeof (struct zyd_softc), 1);
1176e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
1177e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (err != DDI_SUCCESS)
1178e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		return (err);
1179e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
1180e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	mac_init_ops(&zyd_devops, ZYD_DRV_NAME);
1181e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	err = mod_install(&zyd_ml);
1182e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
1183e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (err != DDI_SUCCESS) {
1184e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		mac_fini_ops(&zyd_devops);
1185e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		ddi_soft_state_fini(&zyd_ssp);
1186e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
1187e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
1188e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	return (err);
1189e8da18d8Spengcheng chen - Sun Microsystems - Beijing China }
1190e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
1191e8da18d8Spengcheng chen - Sun Microsystems - Beijing China /*
1192e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * _info module entry point.
1193e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  *
1194e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * Called to obtain information about the module.
1195e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  */
1196e8da18d8Spengcheng chen - Sun Microsystems - Beijing China int
_info(struct modinfo * modinfop)1197e8da18d8Spengcheng chen - Sun Microsystems - Beijing China _info(struct modinfo *modinfop)
1198e8da18d8Spengcheng chen - Sun Microsystems - Beijing China {
1199e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	return (mod_info(&zyd_ml, modinfop));
1200e8da18d8Spengcheng chen - Sun Microsystems - Beijing China }
1201e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
1202e8da18d8Spengcheng chen - Sun Microsystems - Beijing China /*
1203e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * _fini module entry point.
1204e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  *
1205e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * Called when the module is being unloaded.
1206e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  */
1207e8da18d8Spengcheng chen - Sun Microsystems - Beijing China int
_fini(void)1208e8da18d8Spengcheng chen - Sun Microsystems - Beijing China _fini(void)
1209e8da18d8Spengcheng chen - Sun Microsystems - Beijing China {
1210e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	int err;
1211e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
1212e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	err = mod_remove(&zyd_ml);
1213e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (err == DDI_SUCCESS) {
1214e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		mac_fini_ops(&zyd_devops);
1215e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		ddi_soft_state_fini(&zyd_ssp);
1216e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
1217e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
1218e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	return (err);
1219e8da18d8Spengcheng chen - Sun Microsystems - Beijing China }
1220