1 /* $NetBSD: awi.c,v 1.84 2009/09/15 18:37:02 dyoung Exp $ */
4 * Copyright (c) 1999,2000,2001 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
32 * Driver for AMD 802.11 firmware.
33 * Uses am79c930 chip driver to talk to firmware running on the am79c930.
35 * More-or-less a generic ethernet-like if driver, with 802.11 gorp added.
40 * - flush tx queue on resynch.
41 * - clear oactive on "down".
42 * - rewrite copy-into-mbuf code
43 * - mgmt state machine gets stuck retransmitting assoc requests.
45 * - fix device reset so it's more likely to work
46 * - show status goo through ifmedia.
49 * - deal with more 802.11 frames.
50 * - send reassoc request
51 * - deal with reassoc response
52 * - send/deal with disassociation
53 * - deal with "full" access points (no room for me).
58 * - need ioctls for poking at the MIBs
59 * - implement ad-hoc mode (including bss creation).
60 * - decide when to do "ad hoc" vs. infrastructure mode (IFF_LINK flags?)
61 * (focus on inf. mode since that will be needed for ietf)
62 * - deal with DH vs. FH versions of the card
63 * - deal with faster cards (2mb/s)
64 * - ?WEP goo (mmm, rc4) (it looks not particularly useful).
66 * - common 802.11 mibish things.
67 * - common 802.11 media layer.
71 * Driver for AMD 802.11 PCnetMobile firmware.
72 * Uses am79c930 chip driver to talk to firmware running on the am79c930.
74 * The initial version of the driver was written by
75 * Bill Sommerfeld <sommerfeld@NetBSD.org>.
76 * Then the driver module completely rewritten to support cards with DS phy
77 * and to support adhoc mode by Atsushi Onoe <onoe@NetBSD.org>
80 #include <sys/cdefs.h>
81 __KERNEL_RCSID(0, "$NetBSD: awi.c,v 1.84 2009/09/15 18:37:02 dyoung Exp $");
86 #include <sys/param.h>
87 #include <sys/systm.h>
88 #include <sys/kernel.h>
90 #include <sys/malloc.h>
92 #include <sys/socket.h>
93 #include <sys/sockio.h>
94 #include <sys/errno.h>
95 #include <sys/endian.h>
96 #include <sys/device.h>
99 #include <net/if_dl.h>
100 #include <net/if_ether.h>
101 #include <net/if_media.h>
102 #include <net/if_llc.h>
104 #include <net80211/ieee80211_netbsd.h>
105 #include <net80211/ieee80211_var.h>
114 #include <dev/ic/am79c930reg.h>
115 #include <dev/ic/am79c930var.h>
116 #include <dev/ic/awireg.h>
117 #include <dev/ic/awivar.h>
119 static int awi_init(struct ifnet
*);
120 static void awi_stop(struct ifnet
*, int);
121 static void awi_start(struct ifnet
*);
122 static void awi_watchdog(struct ifnet
*);
123 static int awi_ioctl(struct ifnet
*, u_long
, void *);
124 static int awi_media_change(struct ifnet
*);
125 static void awi_media_status(struct ifnet
*, struct ifmediareq
*);
126 static int awi_mode_init(struct awi_softc
*);
127 static void awi_rx_int(struct awi_softc
*);
128 static void awi_tx_int(struct awi_softc
*);
129 static struct mbuf
*awi_devget(struct awi_softc
*, u_int32_t
, u_int16_t
);
130 static int awi_hw_init(struct awi_softc
*);
131 static int awi_init_mibs(struct awi_softc
*);
132 static int awi_mib(struct awi_softc
*, u_int8_t
, u_int8_t
, int);
133 static int awi_cmd(struct awi_softc
*, u_int8_t
, int);
134 static int awi_cmd_wait(struct awi_softc
*);
135 static void awi_cmd_done(struct awi_softc
*);
136 static int awi_next_txd(struct awi_softc
*, int, u_int32_t
*, u_int32_t
*);
137 static int awi_lock(struct awi_softc
*);
138 static void awi_unlock(struct awi_softc
*);
139 static int awi_intr_lock(struct awi_softc
*);
140 static void awi_intr_unlock(struct awi_softc
*);
141 static int awi_newstate(struct ieee80211com
*, enum ieee80211_state
, int);
142 static void awi_recv_mgmt(struct ieee80211com
*, struct mbuf
*,
143 struct ieee80211_node
*, int, int, u_int32_t
);
144 static int awi_send_mgmt(struct ieee80211com
*, struct ieee80211_node
*, int,
146 static struct mbuf
*awi_ether_encap(struct awi_softc
*, struct mbuf
*);
147 static struct mbuf
*awi_ether_modcap(struct awi_softc
*, struct mbuf
*);
149 /* unaligned little endian access */
150 #define LE_READ_2(p) \
151 ((((u_int8_t *)(p))[0] ) | (((u_int8_t *)(p))[1] << 8))
152 #define LE_READ_4(p) \
153 ((((u_int8_t *)(p))[0] ) | (((u_int8_t *)(p))[1] << 8) | \
154 (((u_int8_t *)(p))[2] << 16) | (((u_int8_t *)(p))[3] << 24))
155 #define LE_WRITE_2(p, v) \
156 ((((u_int8_t *)(p))[0] = (((u_int32_t)(v) ) & 0xff)), \
157 (((u_int8_t *)(p))[1] = (((u_int32_t)(v) >> 8) & 0xff)))
158 #define LE_WRITE_4(p, v) \
159 ((((u_int8_t *)(p))[0] = (((u_int32_t)(v) ) & 0xff)), \
160 (((u_int8_t *)(p))[1] = (((u_int32_t)(v) >> 8) & 0xff)), \
161 (((u_int8_t *)(p))[2] = (((u_int32_t)(v) >> 16) & 0xff)), \
162 (((u_int8_t *)(p))[3] = (((u_int32_t)(v) >> 24) & 0xff)))
164 struct awi_chanset awi_chanset
[] = {
165 /* PHY type domain min max def */
166 { AWI_PHY_TYPE_FH
, AWI_REG_DOMAIN_JP
, 6, 17, 6 },
167 { AWI_PHY_TYPE_FH
, AWI_REG_DOMAIN_ES
, 0, 26, 1 },
168 { AWI_PHY_TYPE_FH
, AWI_REG_DOMAIN_FR
, 0, 32, 1 },
169 { AWI_PHY_TYPE_FH
, AWI_REG_DOMAIN_US
, 0, 77, 1 },
170 { AWI_PHY_TYPE_FH
, AWI_REG_DOMAIN_CA
, 0, 77, 1 },
171 { AWI_PHY_TYPE_FH
, AWI_REG_DOMAIN_EU
, 0, 77, 1 },
172 { AWI_PHY_TYPE_DS
, AWI_REG_DOMAIN_JP
, 14, 14, 14 },
173 { AWI_PHY_TYPE_DS
, AWI_REG_DOMAIN_ES
, 10, 11, 10 },
174 { AWI_PHY_TYPE_DS
, AWI_REG_DOMAIN_FR
, 10, 13, 10 },
175 { AWI_PHY_TYPE_DS
, AWI_REG_DOMAIN_US
, 1, 11, 3 },
176 { AWI_PHY_TYPE_DS
, AWI_REG_DOMAIN_CA
, 1, 11, 3 },
177 { AWI_PHY_TYPE_DS
, AWI_REG_DOMAIN_EU
, 1, 13, 3 },
184 #define DPRINTF(X) if (awi_debug) printf X
185 #define DPRINTF2(X) if (awi_debug > 1) printf X
192 awi_attach(struct awi_softc
*sc
)
194 struct ieee80211com
*ic
= &sc
->sc_ic
;
195 struct ifnet
*ifp
= &sc
->sc_if
;
196 int s
, i
, error
, nrate
;
198 enum ieee80211_phymode mode
;
203 sc
->sc_substate
= AWI_ST_NONE
;
204 if ((error
= awi_hw_init(sc
)) != 0) {
205 config_deactivate(&sc
->sc_dev
);
209 error
= awi_init_mibs(sc
);
211 config_deactivate(&sc
->sc_dev
);
217 #ifdef IFF_NOTRAILERS
220 IFF_SIMPLEX
| IFF_BROADCAST
| IFF_MULTICAST
;
221 ifp
->if_ioctl
= awi_ioctl
;
222 ifp
->if_start
= awi_start
;
223 ifp
->if_watchdog
= awi_watchdog
;
224 ifp
->if_init
= awi_init
;
225 ifp
->if_stop
= awi_stop
;
226 IFQ_SET_READY(&ifp
->if_snd
);
227 memcpy(ifp
->if_xname
, device_xname(&sc
->sc_dev
), IFNAMSIZ
);
230 ic
->ic_caps
= IEEE80211_C_WEP
| IEEE80211_C_IBSS
| IEEE80211_C_HOSTAP
;
231 if (sc
->sc_mib_phy
.IEEE_PHY_Type
== AWI_PHY_TYPE_FH
) {
232 ic
->ic_phytype
= IEEE80211_T_FH
;
233 mode
= IEEE80211_MODE_FH
;
235 ic
->ic_phytype
= IEEE80211_T_DS
;
236 ic
->ic_caps
|= IEEE80211_C_AHDEMO
;
237 mode
= IEEE80211_MODE_11B
;
239 ic
->ic_opmode
= IEEE80211_M_STA
;
240 nrate
= sc
->sc_mib_phy
.aSuprt_Data_Rates
[1];
241 memcpy(ic
->ic_sup_rates
[mode
].rs_rates
,
242 sc
->sc_mib_phy
.aSuprt_Data_Rates
+ 2, nrate
);
243 ic
->ic_sup_rates
[mode
].rs_nrates
= nrate
;
244 IEEE80211_ADDR_COPY(ic
->ic_myaddr
, sc
->sc_mib_addr
.aMAC_Address
);
246 printf("%s: IEEE802.11 %s (firmware %s)\n", ifp
->if_xname
,
247 (ic
->ic_phytype
== IEEE80211_T_FH
) ? "FH" : "DS", sc
->sc_banner
);
248 printf("%s: 802.11 address: %s\n", ifp
->if_xname
,
249 ether_sprintf(ic
->ic_myaddr
));
252 ieee80211_ifattach(ic
);
254 sc
->sc_newstate
= ic
->ic_newstate
;
255 ic
->ic_newstate
= awi_newstate
;
257 sc
->sc_recv_mgmt
= ic
->ic_recv_mgmt
;
258 ic
->ic_recv_mgmt
= awi_recv_mgmt
;
260 sc
->sc_send_mgmt
= ic
->ic_send_mgmt
;
261 ic
->ic_send_mgmt
= awi_send_mgmt
;
263 ieee80211_media_init(ic
, awi_media_change
, awi_media_status
);
265 /* Melco compatibility mode. */
266 #define ADD(s, o) ifmedia_add(&ic->ic_media, \
267 IFM_MAKEWORD(IFM_IEEE80211, (s), (o), 0), 0, NULL)
268 ADD(IFM_AUTO
, IFM_FLAG0
);
270 for (i
= 0; i
< nrate
; i
++) {
271 mword
= ieee80211_rate2media(ic
,
272 ic
->ic_sup_rates
[mode
].rs_rates
[i
], mode
);
275 ADD(mword
, IFM_FLAG0
);
279 if ((sc
->sc_sdhook
= shutdownhook_establish(awi_shutdown
, sc
)) == NULL
)
280 printf("%s: WARNING: unable to establish shutdown hook\n",
282 if ((sc
->sc_powerhook
=
283 powerhook_establish(ifp
->if_xname
, awi_power
, sc
)) == NULL
)
284 printf("%s: WARNING: unable to establish power hook\n",
289 /* ready to accept ioctl */
296 awi_detach(struct awi_softc
*sc
)
298 struct ieee80211com
*ic
= &sc
->sc_ic
;
299 struct ifnet
*ifp
= &sc
->sc_if
;
302 if (!sc
->sc_attached
)
308 while (sc
->sc_sleep_cnt
> 0) {
310 (void)tsleep(sc
, PWAIT
, "awidet", 1);
313 ieee80211_ifdetach(ic
);
315 shutdownhook_disestablish(sc
->sc_sdhook
);
316 powerhook_disestablish(sc
->sc_powerhook
);
322 awi_activate(device_t self
, enum devact act
)
324 struct awi_softc
*sc
= device_private(self
);
327 case DVACT_DEACTIVATE
:
328 if_deactivate(&sc
->sc_if
);
336 awi_power(int why
, void *arg
)
338 struct awi_softc
*sc
= arg
;
339 struct ifnet
*ifp
= &sc
->sc_if
;
343 DPRINTF(("awi_power: %d\n", why
));
345 ocansleep
= sc
->sc_cansleep
;
353 if (ifp
->if_flags
& IFF_UP
) {
355 (void)awi_intr(sc
); /* make sure */
358 case PWR_SOFTSUSPEND
:
359 case PWR_SOFTSTANDBY
:
363 sc
->sc_cansleep
= ocansleep
;
368 awi_shutdown(void *arg
)
370 struct awi_softc
*sc
= arg
;
371 struct ifnet
*ifp
= &sc
->sc_if
;
380 struct awi_softc
*sc
= arg
;
382 int handled
= 0, ocansleep
;
384 static const char *intname
[] = {
385 "CMD", "RX", "TX", "SCAN_CMPLT",
386 "CFP_START", "DTIM", "CFP_ENDING", "GROGGY",
387 "TXDATA", "TXBCAST", "TXPS", "TXCF",
388 "TXMGT", "#13", "RXDATA", "RXMGT"
392 if (!sc
->sc_enabled
|| !sc
->sc_enab_intr
||
393 !device_is_active(&sc
->sc_dev
)) {
394 DPRINTF(("awi_intr: stray interrupt: "
395 "enabled %d enab_intr %d invalid %d\n",
396 sc
->sc_enabled
, sc
->sc_enab_intr
,
397 !device_is_active(&sc
->sc_dev
)));
401 am79c930_gcr_setbits(&sc
->sc_chip
,
402 AM79C930_GCR_DISPWDN
| AM79C930_GCR_ECINT
);
403 awi_write_1(sc
, AWI_DIS_PWRDN
, 1);
404 ocansleep
= sc
->sc_cansleep
;
408 if (awi_intr_lock(sc
) != 0)
410 status
= awi_read_1(sc
, AWI_INTSTAT
);
411 awi_write_1(sc
, AWI_INTSTAT
, 0);
412 awi_write_1(sc
, AWI_INTSTAT
, 0);
413 status
|= awi_read_1(sc
, AWI_INTSTAT2
) << 8;
414 awi_write_1(sc
, AWI_INTSTAT2
, 0);
417 if (!sc
->sc_cmd_inprog
)
418 status
&= ~AWI_INT_CMD
; /* make sure */
425 printf("awi_intr: status 0x%04x", status
);
426 for (i
= 0; i
< sizeof(intname
)/sizeof(intname
[0]);
428 if (status
& (1 << i
))
429 printf(" %s", intname
[i
]);
435 if (status
& AWI_INT_RX
)
437 if (status
& AWI_INT_TX
)
439 if (status
& AWI_INT_CMD
)
441 if (status
& AWI_INT_SCAN_CMPLT
) {
442 if (sc
->sc_ic
.ic_state
== IEEE80211_S_SCAN
&&
443 sc
->sc_substate
== AWI_ST_NONE
)
444 ieee80211_next_scan(&sc
->sc_ic
);
447 sc
->sc_cansleep
= ocansleep
;
448 am79c930_gcr_clearbits(&sc
->sc_chip
, AM79C930_GCR_DISPWDN
);
449 awi_write_1(sc
, AWI_DIS_PWRDN
, 0);
455 awi_init(struct ifnet
*ifp
)
457 struct awi_softc
*sc
= ifp
->if_softc
;
458 struct ieee80211com
*ic
= &sc
->sc_ic
;
459 struct ieee80211_node
*ni
= ic
->ic_bss
;
460 struct ieee80211_rateset
*rs
;
463 DPRINTF(("awi_init: enabled=%d\n", sc
->sc_enabled
));
464 if (sc
->sc_enabled
) {
468 (*sc
->sc_enable
)(sc
);
470 if ((error
= awi_hw_init(sc
)) != 0) {
472 (*sc
->sc_disable
)(sc
);
477 ic
->ic_state
= IEEE80211_S_INIT
;
479 ic
->ic_flags
&= ~IEEE80211_F_IBSSON
;
480 switch (ic
->ic_opmode
) {
481 case IEEE80211_M_STA
:
482 sc
->sc_mib_local
.Network_Mode
= 1;
483 sc
->sc_mib_local
.Acting_as_AP
= 0;
485 case IEEE80211_M_IBSS
:
486 ic
->ic_flags
|= IEEE80211_F_IBSSON
;
488 case IEEE80211_M_AHDEMO
:
489 sc
->sc_mib_local
.Network_Mode
= 0;
490 sc
->sc_mib_local
.Acting_as_AP
= 0;
492 case IEEE80211_M_HOSTAP
:
493 sc
->sc_mib_local
.Network_Mode
= 1;
494 sc
->sc_mib_local
.Acting_as_AP
= 1;
496 case IEEE80211_M_MONITOR
:
500 IEEE80211_ADDR_COPY(ic
->ic_myaddr
, CLLADDR(ifp
->if_sadl
));
502 memset(&sc
->sc_mib_mac
.aDesired_ESS_ID
, 0, AWI_ESS_ID_SIZE
);
503 sc
->sc_mib_mac
.aDesired_ESS_ID
[0] = IEEE80211_ELEMID_SSID
;
504 sc
->sc_mib_mac
.aDesired_ESS_ID
[1] = ic
->ic_des_esslen
;
505 memcpy(&sc
->sc_mib_mac
.aDesired_ESS_ID
[2], ic
->ic_des_essid
,
508 /* configure basic rate */
509 if (ic
->ic_phytype
== IEEE80211_T_FH
)
510 rs
= &ic
->ic_sup_rates
[IEEE80211_MODE_FH
];
512 rs
= &ic
->ic_sup_rates
[IEEE80211_MODE_11B
];
513 if (ic
->ic_fixed_rate
!= -1) {
514 rate
= rs
->rs_rates
[ic
->ic_fixed_rate
] & IEEE80211_RATE_VAL
;
517 for (i
= 0; i
< rs
->rs_nrates
; i
++) {
518 if ((rs
->rs_rates
[i
] & IEEE80211_RATE_BASIC
) &&
519 rate
< (rs
->rs_rates
[i
] & IEEE80211_RATE_VAL
))
520 rate
= rs
->rs_rates
[i
] & IEEE80211_RATE_VAL
;
524 LE_WRITE_2(&sc
->sc_mib_mac
.aStation_Basic_Rate
, rate
);
526 if ((error
= awi_mode_init(sc
)) != 0) {
527 DPRINTF(("awi_init: awi_mode_init failed %d\n", error
));
532 /* start transmitter */
533 sc
->sc_txdone
= sc
->sc_txnext
= sc
->sc_txbase
;
534 awi_write_4(sc
, sc
->sc_txbase
+ AWI_TXD_START
, 0);
535 awi_write_4(sc
, sc
->sc_txbase
+ AWI_TXD_NEXT
, 0);
536 awi_write_4(sc
, sc
->sc_txbase
+ AWI_TXD_LENGTH
, 0);
537 awi_write_1(sc
, sc
->sc_txbase
+ AWI_TXD_RATE
, 0);
538 awi_write_4(sc
, sc
->sc_txbase
+ AWI_TXD_NDA
, 0);
539 awi_write_4(sc
, sc
->sc_txbase
+ AWI_TXD_NRA
, 0);
540 awi_write_1(sc
, sc
->sc_txbase
+ AWI_TXD_STATE
, 0);
541 awi_write_4(sc
, AWI_CA_TX_DATA
, sc
->sc_txbase
);
542 awi_write_4(sc
, AWI_CA_TX_MGT
, 0);
543 awi_write_4(sc
, AWI_CA_TX_BCAST
, 0);
544 awi_write_4(sc
, AWI_CA_TX_PS
, 0);
545 awi_write_4(sc
, AWI_CA_TX_CF
, 0);
546 if ((error
= awi_cmd(sc
, AWI_CMD_INIT_TX
, AWI_WAIT
)) != 0) {
547 DPRINTF(("awi_init: failed to start transmitter: %d\n", error
));
553 if ((error
= awi_cmd(sc
, AWI_CMD_INIT_RX
, AWI_WAIT
)) != 0) {
554 DPRINTF(("awi_init: failed to start receiver: %d\n", error
));
558 sc
->sc_rxdoff
= awi_read_4(sc
, AWI_CA_IRX_DATA_DESC
);
559 sc
->sc_rxmoff
= awi_read_4(sc
, AWI_CA_IRX_PS_DESC
);
561 ifp
->if_flags
|= IFF_RUNNING
;
562 ifp
->if_flags
&= ~IFF_OACTIVE
;
563 ic
->ic_state
= IEEE80211_S_INIT
;
565 if (ic
->ic_opmode
== IEEE80211_M_AHDEMO
||
566 ic
->ic_opmode
== IEEE80211_M_HOSTAP
) {
567 ni
->ni_chan
= ic
->ic_ibss_chan
;
568 ni
->ni_intval
= ic
->ic_lintval
;
571 memset(&ni
->ni_tstamp
, 0, sizeof(ni
->ni_tstamp
));
573 ic
->ic_sup_rates
[ieee80211_chan2mode(ic
, ni
->ni_chan
)];
574 IEEE80211_ADDR_COPY(ni
->ni_macaddr
, ic
->ic_myaddr
);
575 if (ic
->ic_opmode
== IEEE80211_M_HOSTAP
) {
576 IEEE80211_ADDR_COPY(ni
->ni_bssid
, ic
->ic_myaddr
);
577 ni
->ni_esslen
= ic
->ic_des_esslen
;
578 memcpy(ni
->ni_essid
, ic
->ic_des_essid
, ni
->ni_esslen
);
579 ni
->ni_capinfo
= IEEE80211_CAPINFO_ESS
;
580 if (ic
->ic_phytype
== IEEE80211_T_FH
) {
581 ni
->ni_fhdwell
= 200; /* XXX */
585 ni
->ni_capinfo
= IEEE80211_CAPINFO_IBSS
;
586 memset(ni
->ni_bssid
, 0, IEEE80211_ADDR_LEN
);
589 if (ic
->ic_flags
& IEEE80211_F_PRIVACY
)
590 ni
->ni_capinfo
|= IEEE80211_CAPINFO_PRIVACY
;
591 if (ic
->ic_opmode
!= IEEE80211_M_AHDEMO
)
592 ic
->ic_flags
|= IEEE80211_F_SIBSS
;
593 ic
->ic_state
= IEEE80211_S_SCAN
; /*XXX*/
594 sc
->sc_substate
= AWI_ST_NONE
;
595 ieee80211_new_state(ic
, IEEE80211_S_RUN
, -1);
597 /* XXX check sc->sc_cur_chan */
598 ni
->ni_chan
= &ic
->ic_channels
[sc
->sc_cur_chan
];
599 ieee80211_new_state(ic
, IEEE80211_S_SCAN
, -1);
605 awi_stop(struct ifnet
*ifp
, int disable
)
607 struct awi_softc
*sc
= ifp
->if_softc
;
612 DPRINTF(("awi_stop(%d)\n", disable
));
614 ieee80211_new_state(&sc
->sc_ic
, IEEE80211_S_INIT
, -1);
616 if (device_is_active(&sc
->sc_dev
)) {
617 if (sc
->sc_cmd_inprog
)
618 (void)awi_cmd_wait(sc
);
619 (void)awi_cmd(sc
, AWI_CMD_KILL_RX
, AWI_WAIT
);
620 sc
->sc_cmd_inprog
= AWI_CMD_FLUSH_TX
;
621 awi_write_1(sc
, AWI_CA_FTX_DATA
, 1);
622 awi_write_1(sc
, AWI_CA_FTX_MGT
, 0);
623 awi_write_1(sc
, AWI_CA_FTX_BCAST
, 0);
624 awi_write_1(sc
, AWI_CA_FTX_PS
, 0);
625 awi_write_1(sc
, AWI_CA_FTX_CF
, 0);
626 (void)awi_cmd(sc
, AWI_CMD_FLUSH_TX
, AWI_WAIT
);
628 ifp
->if_flags
&= ~(IFF_RUNNING
|IFF_OACTIVE
);
630 sc
->sc_tx_timer
= sc
->sc_rx_timer
= 0;
631 if (sc
->sc_rxpend
!= NULL
) {
632 m_freem(sc
->sc_rxpend
);
633 sc
->sc_rxpend
= NULL
;
635 IFQ_PURGE(&ifp
->if_snd
);
638 if (device_is_active(&sc
->sc_dev
))
639 am79c930_gcr_setbits(&sc
->sc_chip
,
640 AM79C930_GCR_CORESET
);
642 (*sc
->sc_disable
)(sc
);
648 awi_start(struct ifnet
*ifp
)
650 struct awi_softc
*sc
= ifp
->if_softc
;
651 struct ieee80211com
*ic
= &sc
->sc_ic
;
652 struct ether_header
*eh
;
653 struct ieee80211_node
*ni
;
654 struct ieee80211_frame
*wh
;
657 u_int32_t txd
, frame
, ntxd
;
660 if (!sc
->sc_enabled
|| !device_is_active(&sc
->sc_dev
))
665 IF_POLL(&ic
->ic_mgtq
, m0
);
668 len
= m0
->m_pkthdr
.len
;
669 if (awi_next_txd(sc
, len
, &frame
, &ntxd
)) {
670 ifp
->if_flags
|= IFF_OACTIVE
;
673 IF_DEQUEUE(&ic
->ic_mgtq
, m0
);
674 ni
= (struct ieee80211_node
*)m0
->m_pkthdr
.rcvif
;
676 if (ic
->ic_state
!= IEEE80211_S_RUN
)
678 IFQ_POLL(&ifp
->if_snd
, m0
);
682 * Need to calculate the real length to determine
683 * if the transmit buffer has a room for the packet.
685 len
= m0
->m_pkthdr
.len
+ sizeof(struct ieee80211_frame
);
686 if (!(ifp
->if_flags
& IFF_LINK0
) && !sc
->sc_adhoc_ap
)
687 len
+= sizeof(struct llc
) -
688 sizeof(struct ether_header
);
689 if (ic
->ic_flags
& IEEE80211_F_PRIVACY
) {
691 len
+= IEEE80211_WEP_IVLEN
+
692 IEEE80211_WEP_KIDLEN
+ IEEE80211_WEP_CRCLEN
;
694 if (awi_next_txd(sc
, len
, &frame
, &ntxd
)) {
695 ifp
->if_flags
|= IFF_OACTIVE
;
698 IFQ_DEQUEUE(&ifp
->if_snd
, m0
);
702 bpf_mtap(ifp
->if_bpf
, m0
);
704 eh
= mtod(m0
, struct ether_header
*);
705 ni
= ieee80211_find_txnode(ic
, eh
->ether_dhost
);
710 if ((ifp
->if_flags
& IFF_LINK0
) || sc
->sc_adhoc_ap
)
711 m0
= awi_ether_encap(sc
, m0
);
713 m0
= ieee80211_encap(ic
, m0
, ni
);
716 ieee80211_free_node(ni
);
720 wh
= mtod(m0
, struct ieee80211_frame
*);
721 if (!IEEE80211_IS_MULTICAST(wh
->i_addr1
) &&
722 (ic
->ic_opmode
== IEEE80211_M_HOSTAP
||
723 ic
->ic_opmode
== IEEE80211_M_IBSS
) &&
724 sc
->sc_adhoc_ap
== 0 &&
725 (ifp
->if_flags
& IFF_LINK0
) == 0 &&
726 (wh
->i_fc
[0] & IEEE80211_FC0_TYPE_MASK
) ==
727 IEEE80211_FC0_TYPE_DATA
) {
729 ieee80211_free_node(ni
);
736 bpf_mtap(ic
->ic_rawbpf
, m0
);
739 if ((ieee80211_crypto_encap(ic
, ni
, m0
)) == NULL
) {
741 ieee80211_free_node(ni
);
746 ieee80211_free_node(ni
);
748 if (m0
->m_pkthdr
.len
!= len
) {
749 printf("%s: length %d should be %d\n",
750 sc
->sc_if
.if_xname
, m0
->m_pkthdr
.len
, len
);
757 if ((ifp
->if_flags
& IFF_DEBUG
) && (ifp
->if_flags
& IFF_LINK2
))
758 ieee80211_dump_pkt(m0
->m_data
, m0
->m_len
,
759 ic
->ic_bss
->ni_rates
.
760 rs_rates
[ic
->ic_bss
->ni_txrate
] &
761 IEEE80211_RATE_VAL
, -1);
763 for (m
= m0
, len
= 0; m
!= NULL
; m
= m
->m_next
) {
764 awi_write_bytes(sc
, frame
+ len
, mtod(m
, u_int8_t
*),
769 rate
= (ic
->ic_bss
->ni_rates
.rs_rates
[ic
->ic_bss
->ni_txrate
] &
770 IEEE80211_RATE_VAL
) * 5;
771 awi_write_1(sc
, ntxd
+ AWI_TXD_STATE
, 0);
772 awi_write_4(sc
, txd
+ AWI_TXD_START
, frame
);
773 awi_write_4(sc
, txd
+ AWI_TXD_NEXT
, ntxd
);
774 awi_write_4(sc
, txd
+ AWI_TXD_LENGTH
, len
);
775 awi_write_1(sc
, txd
+ AWI_TXD_RATE
, rate
);
776 awi_write_4(sc
, txd
+ AWI_TXD_NDA
, 0);
777 awi_write_4(sc
, txd
+ AWI_TXD_NRA
, 0);
778 awi_write_1(sc
, txd
+ AWI_TXD_STATE
, AWI_TXD_ST_OWN
);
779 sc
->sc_txnext
= ntxd
;
787 awi_watchdog(struct ifnet
*ifp
)
789 struct awi_softc
*sc
= ifp
->if_softc
;
794 if (!sc
->sc_enabled
|| !device_is_active(&sc
->sc_dev
))
797 ocansleep
= sc
->sc_cansleep
;
799 if (sc
->sc_tx_timer
) {
800 if (--sc
->sc_tx_timer
== 0) {
801 printf("%s: device timeout\n", ifp
->if_xname
);
802 prevdone
= sc
->sc_txdone
;
804 if (sc
->sc_txdone
== prevdone
) {
812 if (sc
->sc_rx_timer
) {
813 if (--sc
->sc_rx_timer
== 0) {
814 if (sc
->sc_ic
.ic_state
== IEEE80211_S_RUN
) {
815 ieee80211_new_state(&sc
->sc_ic
,
816 IEEE80211_S_SCAN
, -1);
822 /* TODO: rate control */
823 ieee80211_watchdog(&sc
->sc_ic
);
825 sc
->sc_cansleep
= ocansleep
;
829 awi_ioctl(struct ifnet
*ifp
, u_long cmd
, void *data
)
831 struct awi_softc
*sc
= ifp
->if_softc
;
832 struct ifreq
*ifr
= (struct ifreq
*)data
;
836 /* serialize ioctl, since we may sleep */
837 if ((error
= awi_lock(sc
)) != 0)
842 if ((error
= ifioctl_common(ifp
, cmd
, data
)) != 0)
844 if (ifp
->if_flags
& IFF_UP
) {
845 if (sc
->sc_enabled
) {
847 * To avoid rescanning another access point,
848 * do not call awi_init() here. Instead,
849 * only reflect promisc mode settings.
851 error
= awi_mode_init(sc
);
853 error
= awi_init(ifp
);
854 } else if (sc
->sc_enabled
)
859 error
= ifmedia_ioctl(ifp
, ifr
, &sc
->sc_ic
.ic_media
, cmd
);
863 error
= ether_ioctl(ifp
, cmd
, data
);
864 if (error
== ENETRESET
) {
866 if (ifp
->if_flags
& IFF_RUNNING
)
867 error
= awi_mode_init(sc
);
873 error
= ieee80211_ioctl(&sc
->sc_ic
, cmd
, data
);
874 if (error
== ENETRESET
) {
876 error
= awi_init(ifp
);
889 * Called from ifmedia_ioctl via awi_ioctl with lock obtained.
891 * TBD factor with ieee80211_media_change
894 awi_media_change(struct ifnet
*ifp
)
896 struct awi_softc
*sc
= ifp
->if_softc
;
897 struct ieee80211com
*ic
= &sc
->sc_ic
;
898 struct ifmedia_entry
*ime
;
899 enum ieee80211_opmode newmode
;
900 int i
, rate
, newadhoc_ap
, error
= 0;
902 ime
= ic
->ic_media
.ifm_cur
;
903 if (IFM_SUBTYPE(ime
->ifm_media
) == IFM_AUTO
) {
906 struct ieee80211_rateset
*rs
=
907 &ic
->ic_sup_rates
[(ic
->ic_phytype
== IEEE80211_T_FH
)
908 ? IEEE80211_MODE_FH
: IEEE80211_MODE_11B
];
909 rate
= ieee80211_media2rate(ime
->ifm_media
);
912 for (i
= 0; i
< rs
->rs_nrates
; i
++) {
913 if ((rs
->rs_rates
[i
] & IEEE80211_RATE_VAL
) == rate
)
916 if (i
== rs
->rs_nrates
)
919 if (ic
->ic_fixed_rate
!= i
) {
920 ic
->ic_fixed_rate
= i
;
925 * combination of mediaopt
927 * hostap adhoc flag0 opmode adhoc_ap comment
928 * + - - HOSTAP 0 HostAP
930 * - + + AHDEMO 0 WaveLAN adhoc
931 * - - + IBSS 1 Melco old Sta
933 * - - - STA 0 Infra Station
936 if (ime
->ifm_media
& IFM_IEEE80211_HOSTAP
)
937 newmode
= IEEE80211_M_HOSTAP
;
938 else if (ime
->ifm_media
& IFM_IEEE80211_ADHOC
) {
939 if (ic
->ic_phytype
== IEEE80211_T_DS
&&
940 (ime
->ifm_media
& IFM_FLAG0
))
941 newmode
= IEEE80211_M_AHDEMO
;
943 newmode
= IEEE80211_M_IBSS
;
944 } else if (ime
->ifm_media
& IFM_FLAG0
) {
945 newmode
= IEEE80211_M_IBSS
;
948 newmode
= IEEE80211_M_STA
;
949 if (ic
->ic_opmode
!= newmode
|| sc
->sc_adhoc_ap
!= newadhoc_ap
) {
950 ic
->ic_opmode
= newmode
;
951 sc
->sc_adhoc_ap
= newadhoc_ap
;
955 if (error
== ENETRESET
) {
957 error
= awi_init(ifp
);
965 awi_media_status(struct ifnet
*ifp
, struct ifmediareq
*imr
)
967 struct awi_softc
*sc
= ifp
->if_softc
;
968 struct ieee80211com
*ic
= &sc
->sc_ic
;
970 enum ieee80211_phymode mode
;
972 imr
->ifm_status
= IFM_AVALID
;
973 if (ic
->ic_state
== IEEE80211_S_RUN
)
974 imr
->ifm_status
|= IFM_ACTIVE
;
975 imr
->ifm_active
= IFM_IEEE80211
;
976 if (ic
->ic_phytype
== IEEE80211_T_FH
)
977 mode
= IEEE80211_MODE_FH
;
979 mode
= IEEE80211_MODE_11B
;
980 if (ic
->ic_state
== IEEE80211_S_RUN
) {
981 rate
= ic
->ic_bss
->ni_rates
.rs_rates
[ic
->ic_bss
->ni_txrate
] &
984 if (ic
->ic_fixed_rate
== -1)
987 rate
= ic
->ic_sup_rates
[mode
].
988 rs_rates
[ic
->ic_fixed_rate
] & IEEE80211_RATE_VAL
;
990 imr
->ifm_active
|= ieee80211_rate2media(ic
, rate
, mode
);
991 switch (ic
->ic_opmode
) {
992 case IEEE80211_M_MONITOR
: /* we should never reach here */
994 case IEEE80211_M_STA
:
996 case IEEE80211_M_IBSS
:
998 imr
->ifm_active
|= IFM_FLAG0
;
1000 imr
->ifm_active
|= IFM_IEEE80211_ADHOC
;
1002 case IEEE80211_M_AHDEMO
:
1003 imr
->ifm_active
|= IFM_IEEE80211_ADHOC
| IFM_FLAG0
;
1005 case IEEE80211_M_HOSTAP
:
1006 imr
->ifm_active
|= IFM_IEEE80211_HOSTAP
;
1012 awi_mode_init(struct awi_softc
*sc
)
1014 struct ifnet
*ifp
= &sc
->sc_if
;
1016 struct ether_multi
*enm
;
1017 struct ether_multistep step
;
1019 /* reinitialize muticast filter */
1021 sc
->sc_mib_local
.Accept_All_Multicast_Dis
= 0;
1022 if (sc
->sc_ic
.ic_opmode
!= IEEE80211_M_HOSTAP
&&
1023 (ifp
->if_flags
& IFF_PROMISC
)) {
1024 sc
->sc_mib_mac
.aPromiscuous_Enable
= 1;
1027 sc
->sc_mib_mac
.aPromiscuous_Enable
= 0;
1028 ETHER_FIRST_MULTI(step
, &sc
->sc_ec
, enm
);
1029 while (enm
!= NULL
) {
1030 if (n
== AWI_GROUP_ADDR_SIZE
||
1031 !IEEE80211_ADDR_EQ(enm
->enm_addrlo
, enm
->enm_addrhi
))
1033 IEEE80211_ADDR_COPY(sc
->sc_mib_addr
.aGroup_Addresses
[n
],
1036 ETHER_NEXT_MULTI(step
, enm
);
1038 for (; n
< AWI_GROUP_ADDR_SIZE
; n
++)
1039 memset(sc
->sc_mib_addr
.aGroup_Addresses
[n
], 0,
1040 IEEE80211_ADDR_LEN
);
1041 sc
->sc_mib_local
.Accept_All_Multicast_Dis
= 1;
1044 if (sc
->sc_mib_local
.Accept_All_Multicast_Dis
)
1045 ifp
->if_flags
&= ~IFF_ALLMULTI
;
1047 ifp
->if_flags
|= IFF_ALLMULTI
;
1048 sc
->sc_mib_mgt
.Wep_Required
=
1049 (sc
->sc_ic
.ic_flags
& IEEE80211_F_PRIVACY
) ? AWI_WEP_ON
: AWI_WEP_OFF
;
1051 if ((error
= awi_mib(sc
, AWI_CMD_SET_MIB
, AWI_MIB_LOCAL
, AWI_WAIT
)) ||
1052 (error
= awi_mib(sc
, AWI_CMD_SET_MIB
, AWI_MIB_ADDR
, AWI_WAIT
)) ||
1053 (error
= awi_mib(sc
, AWI_CMD_SET_MIB
, AWI_MIB_MAC
, AWI_WAIT
)) ||
1054 (error
= awi_mib(sc
, AWI_CMD_SET_MIB
, AWI_MIB_MGT
, AWI_WAIT
)) ||
1055 (error
= awi_mib(sc
, AWI_CMD_SET_MIB
, AWI_MIB_PHY
, AWI_WAIT
))) {
1056 DPRINTF(("awi_mode_init: MIB set failed: %d\n", error
));
1063 awi_rx_int(struct awi_softc
*sc
)
1065 struct ieee80211com
*ic
= &sc
->sc_ic
;
1066 struct ifnet
*ifp
= &sc
->sc_if
;
1067 struct ieee80211_frame_min
*wh
;
1068 struct ieee80211_node
*ni
;
1069 u_int8_t state
, rate
, rssi
;
1071 u_int32_t frame
, next
, rstamp
, rxoff
;
1074 rxoff
= sc
->sc_rxdoff
;
1076 state
= awi_read_1(sc
, rxoff
+ AWI_RXD_HOST_DESC_STATE
);
1077 if (state
& AWI_RXD_ST_OWN
)
1079 if (!(state
& AWI_RXD_ST_CONSUMED
)) {
1080 if (sc
->sc_substate
!= AWI_ST_NONE
)
1082 if (state
& AWI_RXD_ST_RXERROR
) {
1086 len
= awi_read_2(sc
, rxoff
+ AWI_RXD_LEN
);
1087 rate
= awi_read_1(sc
, rxoff
+ AWI_RXD_RATE
);
1088 rssi
= awi_read_1(sc
, rxoff
+ AWI_RXD_RSSI
);
1089 frame
= awi_read_4(sc
, rxoff
+ AWI_RXD_START_FRAME
) &
1091 rstamp
= awi_read_4(sc
, rxoff
+ AWI_RXD_LOCALTIME
);
1092 m
= awi_devget(sc
, frame
, len
);
1097 if (state
& AWI_RXD_ST_LF
) {
1098 /* TODO check my bss */
1099 if (!(sc
->sc_ic
.ic_flags
& IEEE80211_F_SIBSS
) &&
1100 sc
->sc_ic
.ic_state
== IEEE80211_S_RUN
) {
1101 sc
->sc_rx_timer
= 10;
1104 if ((ifp
->if_flags
& IFF_DEBUG
) &&
1105 (ifp
->if_flags
& IFF_LINK2
))
1106 ieee80211_dump_pkt(m
->m_data
, m
->m_len
,
1108 if ((ifp
->if_flags
& IFF_LINK0
) ||
1110 m
= awi_ether_modcap(sc
, m
);
1112 m
= m_pullup(m
, sizeof(*wh
));
1117 wh
= mtod(m
, struct ieee80211_frame_min
*);
1118 ni
= ieee80211_find_rxnode(ic
, wh
);
1119 ieee80211_input(ic
, m
, ni
, rssi
, rstamp
);
1121 * The frame may have caused the
1122 * node to be marked for reclamation
1123 * (e.g. in response to a DEAUTH
1124 * message) so use release_node here
1125 * instead of unref_node.
1127 ieee80211_free_node(ni
);
1131 state
|= AWI_RXD_ST_CONSUMED
;
1132 awi_write_1(sc
, rxoff
+ AWI_RXD_HOST_DESC_STATE
, state
);
1134 next
= awi_read_4(sc
, rxoff
+ AWI_RXD_NEXT
);
1135 if (next
& AWI_RXD_NEXT_LAST
)
1137 /* make sure the next pointer is correct */
1138 if (next
!= awi_read_4(sc
, rxoff
+ AWI_RXD_NEXT
))
1140 state
|= AWI_RXD_ST_OWN
;
1141 awi_write_1(sc
, rxoff
+ AWI_RXD_HOST_DESC_STATE
, state
);
1142 rxoff
= next
& 0x7fff;
1144 sc
->sc_rxdoff
= rxoff
;
1148 awi_tx_int(struct awi_softc
*sc
)
1150 struct ifnet
*ifp
= &sc
->sc_if
;
1153 while (sc
->sc_txdone
!= sc
->sc_txnext
) {
1154 flags
= awi_read_1(sc
, sc
->sc_txdone
+ AWI_TXD_STATE
);
1155 if ((flags
& AWI_TXD_ST_OWN
) || !(flags
& AWI_TXD_ST_DONE
))
1157 if (flags
& AWI_TXD_ST_ERROR
)
1159 sc
->sc_txdone
= awi_read_4(sc
, sc
->sc_txdone
+ AWI_TXD_NEXT
) &
1162 DPRINTF2(("awi_txint: txdone %d txnext %d txbase %d txend %d\n",
1163 sc
->sc_txdone
, sc
->sc_txnext
, sc
->sc_txbase
, sc
->sc_txend
));
1164 sc
->sc_tx_timer
= 0;
1165 ifp
->if_flags
&= ~IFF_OACTIVE
;
1169 static struct mbuf
*
1170 awi_devget(struct awi_softc
*sc
, u_int32_t off
, u_int16_t len
)
1172 struct ifnet
*ifp
= &sc
->sc_if
;
1174 struct mbuf
*top
, **mp
;
1177 top
= sc
->sc_rxpend
;
1180 sc
->sc_rxpend
= NULL
;
1181 top
->m_pkthdr
.len
+= len
;
1183 while (*mp
!= NULL
) {
1187 if (m
->m_flags
& M_EXT
)
1188 tlen
= m
->m_ext
.ext_size
;
1189 else if (m
->m_flags
& M_PKTHDR
)
1196 awi_read_bytes(sc
, off
, mtod(m
, u_int8_t
*) + m
->m_len
, tlen
);
1203 MGETHDR(m
, M_DONTWAIT
, MT_DATA
);
1206 m
->m_pkthdr
.rcvif
= ifp
;
1207 m
->m_pkthdr
.len
= len
;
1209 m
->m_flags
|= M_HASFCS
;
1211 MGET(m
, M_DONTWAIT
, MT_DATA
);
1218 if (len
>= MINCLSIZE
) {
1219 MCLGET(m
, M_DONTWAIT
);
1220 if (m
->m_flags
& M_EXT
)
1221 m
->m_len
= m
->m_ext
.ext_size
;
1224 int hdrlen
= sizeof(struct ieee80211_frame
) +
1226 char *newdata
= (char *)
1227 ALIGN(m
->m_data
+ hdrlen
) - hdrlen
;
1228 m
->m_len
-= newdata
- m
->m_data
;
1229 m
->m_data
= newdata
;
1233 awi_read_bytes(sc
, off
, mtod(m
, u_int8_t
*), m
->m_len
);
1243 * Initialize hardware and start firmware to accept commands.
1244 * Called everytime after power on firmware.
1248 awi_hw_init(struct awi_softc
*sc
)
1254 sc
->sc_enab_intr
= 0;
1255 awi_drvstate(sc
, AWI_DRV_RESET
);
1257 /* reset firmware */
1258 am79c930_gcr_setbits(&sc
->sc_chip
, AM79C930_GCR_CORESET
);
1260 awi_write_1(sc
, AWI_SELFTEST
, 0);
1261 awi_write_1(sc
, AWI_CMD
, 0);
1262 awi_write_1(sc
, AWI_BANNER
, 0);
1263 am79c930_gcr_clearbits(&sc
->sc_chip
, AM79C930_GCR_CORESET
);
1266 /* wait for selftest completion */
1267 for (i
= 0; ; i
++) {
1268 if (!device_is_active(&sc
->sc_dev
))
1270 if (i
>= AWI_SELFTEST_TIMEOUT
*hz
/1000) {
1271 printf("%s: failed to complete selftest (timeout)\n",
1272 sc
->sc_if
.if_xname
);
1275 status
= awi_read_1(sc
, AWI_SELFTEST
);
1276 if ((status
& 0xf0) == 0xf0)
1278 if (sc
->sc_cansleep
) {
1280 (void)tsleep(sc
, PWAIT
, "awitst", 1);
1283 DELAY(1000*1000/hz
);
1286 if (status
!= AWI_SELFTEST_PASSED
) {
1287 printf("%s: failed to complete selftest (code %x)\n",
1288 sc
->sc_if
.if_xname
, status
);
1292 /* check banner to confirm firmware write it */
1293 awi_read_bytes(sc
, AWI_BANNER
, sc
->sc_banner
, AWI_BANNER_LEN
);
1294 if (memcmp(sc
->sc_banner
, "PCnetMobile:", 12) != 0) {
1295 printf("%s: failed to complete selftest (bad banner)\n",
1296 sc
->sc_if
.if_xname
);
1297 for (i
= 0; i
< AWI_BANNER_LEN
; i
++)
1298 printf("%s%02x", i
? ":" : "\t", sc
->sc_banner
[i
]);
1303 /* initializing interrupt */
1304 sc
->sc_enab_intr
= 1;
1305 error
= awi_intr_lock(sc
);
1308 intmask
= AWI_INT_GROGGY
| AWI_INT_SCAN_CMPLT
|
1309 AWI_INT_TX
| AWI_INT_RX
| AWI_INT_CMD
;
1310 awi_write_1(sc
, AWI_INTMASK
, ~intmask
& 0xff);
1311 awi_write_1(sc
, AWI_INTMASK2
, 0);
1312 awi_write_1(sc
, AWI_INTSTAT
, 0);
1313 awi_write_1(sc
, AWI_INTSTAT2
, 0);
1314 awi_intr_unlock(sc
);
1315 am79c930_gcr_setbits(&sc
->sc_chip
, AM79C930_GCR_ENECINT
);
1317 /* issuing interface test command */
1318 error
= awi_cmd(sc
, AWI_CMD_NOP
, AWI_WAIT
);
1320 printf("%s: failed to complete selftest",
1321 sc
->sc_if
.if_xname
);
1323 printf(" (no hardware)\n");
1324 else if (error
!= EWOULDBLOCK
)
1325 printf(" (error %d)\n", error
);
1326 else if (sc
->sc_cansleep
)
1327 printf(" (lost interrupt)\n");
1329 printf(" (command timeout)\n");
1333 /* Initialize VBM */
1334 awi_write_1(sc
, AWI_VBM_OFFSET
, 0);
1335 awi_write_1(sc
, AWI_VBM_LENGTH
, 1);
1336 awi_write_1(sc
, AWI_VBM_BITMAP
, 0);
1341 * Extract the factory default MIB value from firmware and assign the driver
1343 * Called once at attaching the interface.
1347 awi_init_mibs(struct awi_softc
*sc
)
1350 struct ieee80211com
*ic
= &sc
->sc_ic
;
1351 struct awi_chanset
*cs
;
1353 if ((error
= awi_mib(sc
, AWI_CMD_GET_MIB
, AWI_MIB_LOCAL
, AWI_WAIT
)) ||
1354 (error
= awi_mib(sc
, AWI_CMD_GET_MIB
, AWI_MIB_ADDR
, AWI_WAIT
)) ||
1355 (error
= awi_mib(sc
, AWI_CMD_GET_MIB
, AWI_MIB_MAC
, AWI_WAIT
)) ||
1356 (error
= awi_mib(sc
, AWI_CMD_GET_MIB
, AWI_MIB_MGT
, AWI_WAIT
)) ||
1357 (error
= awi_mib(sc
, AWI_CMD_GET_MIB
, AWI_MIB_PHY
, AWI_WAIT
))) {
1358 printf("%s: failed to get default mib value (error %d)\n",
1359 sc
->sc_if
.if_xname
, error
);
1363 memset(&sc
->sc_ic
.ic_chan_avail
, 0, sizeof(sc
->sc_ic
.ic_chan_avail
));
1364 for (cs
= awi_chanset
; ; cs
++) {
1365 if (cs
->cs_type
== 0) {
1366 printf("%s: failed to set available channel\n",
1367 sc
->sc_if
.if_xname
);
1370 if (cs
->cs_type
== sc
->sc_mib_phy
.IEEE_PHY_Type
&&
1371 cs
->cs_region
== sc
->sc_mib_phy
.aCurrent_Reg_Domain
)
1374 if (sc
->sc_mib_phy
.IEEE_PHY_Type
== AWI_PHY_TYPE_FH
) {
1375 for (i
= cs
->cs_min
; i
<= cs
->cs_max
; i
++) {
1376 chan
= IEEE80211_FH_CHAN(i
% 3 + 1, i
);
1377 setbit(sc
->sc_ic
.ic_chan_avail
, chan
);
1378 /* XXX for FHSS, does frequency matter? */
1379 ic
->ic_channels
[chan
].ic_freq
= 0;
1380 ic
->ic_channels
[chan
].ic_flags
= IEEE80211_CHAN_FHSS
;
1382 * According to the IEEE 802.11 specification,
1383 * hop pattern parameter for FH phy should be
1384 * incremented by 3 for given hop chanset, i.e.,
1385 * the chanset parameter is calculated for given
1386 * hop patter. However, BayStack 650 Access Points
1387 * apparently use fixed hop chanset parameter value
1388 * 1 for any hop pattern. So we also try this
1389 * combination of hop chanset and pattern.
1391 chan
= IEEE80211_FH_CHAN(1, i
);
1392 setbit(sc
->sc_ic
.ic_chan_avail
, chan
);
1393 ic
->ic_channels
[chan
].ic_freq
= 0; /* XXX */
1394 ic
->ic_channels
[chan
].ic_flags
= IEEE80211_CHAN_FHSS
;
1397 for (i
= cs
->cs_min
; i
<= cs
->cs_max
; i
++) {
1398 setbit(sc
->sc_ic
.ic_chan_avail
, i
);
1399 ic
->ic_channels
[i
].ic_freq
=
1400 ieee80211_ieee2mhz(i
, IEEE80211_CHAN_2GHZ
);
1401 ic
->ic_channels
[i
].ic_flags
= IEEE80211_CHAN_B
;
1404 sc
->sc_cur_chan
= cs
->cs_def
;
1405 ic
->ic_ibss_chan
= &ic
->ic_channels
[cs
->cs_def
];
1407 sc
->sc_mib_local
.Fragmentation_Dis
= 1;
1408 sc
->sc_mib_local
.Add_PLCP_Dis
= 0;
1409 sc
->sc_mib_local
.MAC_Hdr_Prsv
= 0;
1410 sc
->sc_mib_local
.Rx_Mgmt_Que_En
= 0;
1411 sc
->sc_mib_local
.Re_Assembly_Dis
= 1;
1412 sc
->sc_mib_local
.Strip_PLCP_Dis
= 0;
1413 sc
->sc_mib_local
.Power_Saving_Mode_Dis
= 1;
1414 sc
->sc_mib_local
.Accept_All_Multicast_Dis
= 1;
1415 sc
->sc_mib_local
.Check_Seq_Cntl_Dis
= 0;
1416 sc
->sc_mib_local
.Flush_CFP_Queue_On_CF_End
= 0;
1417 sc
->sc_mib_local
.Network_Mode
= 1;
1418 sc
->sc_mib_local
.PWD_Lvl
= 0;
1419 sc
->sc_mib_local
.CFP_Mode
= 0;
1421 /* allocate buffers */
1422 sc
->sc_txbase
= AWI_BUFFERS
;
1423 sc
->sc_txend
= sc
->sc_txbase
+
1424 (AWI_TXD_SIZE
+ sizeof(struct ieee80211_frame
) +
1425 sizeof(struct ether_header
) + ETHERMTU
) * AWI_NTXBUFS
;
1426 LE_WRITE_4(&sc
->sc_mib_local
.Tx_Buffer_Offset
, sc
->sc_txbase
);
1427 LE_WRITE_4(&sc
->sc_mib_local
.Tx_Buffer_Size
,
1428 sc
->sc_txend
- sc
->sc_txbase
);
1429 LE_WRITE_4(&sc
->sc_mib_local
.Rx_Buffer_Offset
, sc
->sc_txend
);
1430 LE_WRITE_4(&sc
->sc_mib_local
.Rx_Buffer_Size
,
1431 AWI_BUFFERS_END
- sc
->sc_txend
);
1432 sc
->sc_mib_local
.Acting_as_AP
= 0;
1433 sc
->sc_mib_local
.Fill_CFP
= 0;
1435 memset(&sc
->sc_mib_mac
.aDesired_ESS_ID
, 0, AWI_ESS_ID_SIZE
);
1436 sc
->sc_mib_mac
.aDesired_ESS_ID
[0] = IEEE80211_ELEMID_SSID
;
1438 sc
->sc_mib_mgt
.aPower_Mgt_Mode
= 0;
1439 sc
->sc_mib_mgt
.aDTIM_Period
= 1;
1440 LE_WRITE_2(&sc
->sc_mib_mgt
.aATIM_Window
, 0);
1445 awi_mib(struct awi_softc
*sc
, u_int8_t cmd
, u_int8_t mib
, int wflag
)
1448 u_int8_t size
, *ptr
;
1452 ptr
= (u_int8_t
*)&sc
->sc_mib_local
;
1453 size
= sizeof(sc
->sc_mib_local
);
1456 ptr
= (u_int8_t
*)&sc
->sc_mib_addr
;
1457 size
= sizeof(sc
->sc_mib_addr
);
1460 ptr
= (u_int8_t
*)&sc
->sc_mib_mac
;
1461 size
= sizeof(sc
->sc_mib_mac
);
1464 ptr
= (u_int8_t
*)&sc
->sc_mib_stat
;
1465 size
= sizeof(sc
->sc_mib_stat
);
1468 ptr
= (u_int8_t
*)&sc
->sc_mib_mgt
;
1469 size
= sizeof(sc
->sc_mib_mgt
);
1472 ptr
= (u_int8_t
*)&sc
->sc_mib_phy
;
1473 size
= sizeof(sc
->sc_mib_phy
);
1478 if (sc
->sc_cmd_inprog
) {
1479 if ((error
= awi_cmd_wait(sc
)) != 0) {
1480 if (error
== EWOULDBLOCK
) {
1481 DPRINTF(("awi_mib: cmd %d inprog",
1482 sc
->sc_cmd_inprog
));
1487 sc
->sc_cmd_inprog
= cmd
;
1488 if (cmd
== AWI_CMD_SET_MIB
)
1489 awi_write_bytes(sc
, AWI_CA_MIB_DATA
, ptr
, size
);
1490 awi_write_1(sc
, AWI_CA_MIB_TYPE
, mib
);
1491 awi_write_1(sc
, AWI_CA_MIB_SIZE
, size
);
1492 awi_write_1(sc
, AWI_CA_MIB_INDEX
, 0);
1493 if ((error
= awi_cmd(sc
, cmd
, wflag
)) != 0)
1495 if (cmd
== AWI_CMD_GET_MIB
) {
1496 awi_read_bytes(sc
, AWI_CA_MIB_DATA
, ptr
, size
);
1501 printf("awi_mib: #%d:", mib
);
1502 for (i
= 0; i
< size
; i
++)
1503 printf(" %02x", ptr
[i
]);
1512 awi_cmd(struct awi_softc
*sc
, u_int8_t cmd
, int wflag
)
1517 static const char *cmdname
[] = {
1518 "IDLE", "NOP", "SET_MIB", "INIT_TX", "FLUSH_TX", "INIT_RX",
1519 "KILL_RX", "SLEEP", "WAKE", "GET_MIB", "SCAN", "SYNC", "RESUME"
1524 if (awi_debug
> 1) {
1525 if (cmd
>= sizeof(cmdname
)/sizeof(cmdname
[0]))
1526 printf("awi_cmd: #%d", cmd
);
1528 printf("awi_cmd: %s", cmdname
[cmd
]);
1529 printf(" %s\n", wflag
== AWI_NOWAIT
? "nowait" : "wait");
1532 sc
->sc_cmd_inprog
= cmd
;
1533 awi_write_1(sc
, AWI_CMD_STATUS
, AWI_STAT_IDLE
);
1534 awi_write_1(sc
, AWI_CMD
, cmd
);
1535 if (wflag
== AWI_NOWAIT
)
1537 if ((error
= awi_cmd_wait(sc
)) != 0)
1539 status
= awi_read_1(sc
, AWI_CMD_STATUS
);
1540 awi_write_1(sc
, AWI_CMD
, 0);
1544 case AWI_STAT_BADPARM
:
1547 printf("%s: command %d failed %x\n",
1548 sc
->sc_if
.if_xname
, cmd
, status
);
1555 awi_cmd_wait(struct awi_softc
*sc
)
1560 while (sc
->sc_cmd_inprog
) {
1561 if (!device_is_active(&sc
->sc_dev
))
1563 if (awi_read_1(sc
, AWI_CMD
) != sc
->sc_cmd_inprog
) {
1564 printf("%s: failed to access hardware\n",
1565 sc
->sc_if
.if_xname
);
1566 config_deactivate(&sc
->sc_dev
);
1569 if (sc
->sc_cansleep
) {
1571 error
= tsleep(sc
, PWAIT
, "awicmd",
1572 AWI_CMD_TIMEOUT
*hz
/1000);
1575 if (awi_read_1(sc
, AWI_CMD_STATUS
) != AWI_STAT_IDLE
) {
1579 if (i
++ >= AWI_CMD_TIMEOUT
*1000/10)
1580 error
= EWOULDBLOCK
;
1588 DPRINTF(("awi_cmd_wait: cmd 0x%x, error %d\n",
1589 sc
->sc_cmd_inprog
, error
));
1595 awi_cmd_done(struct awi_softc
*sc
)
1597 u_int8_t cmd
, status
;
1599 status
= awi_read_1(sc
, AWI_CMD_STATUS
);
1600 if (status
== AWI_STAT_IDLE
)
1601 return; /* stray interrupt */
1603 cmd
= sc
->sc_cmd_inprog
;
1604 sc
->sc_cmd_inprog
= 0;
1606 awi_write_1(sc
, AWI_CMD
, 0);
1608 if (status
!= AWI_STAT_OK
) {
1609 printf("%s: command %d failed %x\n",
1610 sc
->sc_if
.if_xname
, cmd
, status
);
1611 sc
->sc_substate
= AWI_ST_NONE
;
1614 if (sc
->sc_substate
!= AWI_ST_NONE
)
1615 (void)ieee80211_new_state(&sc
->sc_ic
, sc
->sc_nstate
, -1);
1619 awi_next_txd(struct awi_softc
*sc
, int len
, u_int32_t
*framep
, u_int32_t
*ntxdp
)
1621 u_int32_t txd
, ntxd
, frame
;
1623 txd
= sc
->sc_txnext
;
1624 frame
= txd
+ AWI_TXD_SIZE
;
1625 if (frame
+ len
> sc
->sc_txend
)
1626 frame
= sc
->sc_txbase
;
1628 if (ntxd
+ AWI_TXD_SIZE
> sc
->sc_txend
)
1629 ntxd
= sc
->sc_txbase
;
1633 * Determine if there are any room in ring buffer.
1634 * --- send wait, === new data, +++ conflict (ENOBUFS)
1635 * base........................end
1636 * done----txd=====ntxd OK
1637 * --txd=====done++++ntxd-- full
1638 * --txd=====ntxd done-- OK
1639 * ==ntxd done----txd=== OK
1640 * ==done++++ntxd----txd=== full
1641 * ++ntxd txd=====done++ full
1644 if (txd
< sc
->sc_txdone
&& ntxd
+ AWI_TXD_SIZE
> sc
->sc_txdone
)
1647 if (txd
< sc
->sc_txdone
|| ntxd
+ AWI_TXD_SIZE
> sc
->sc_txdone
)
1654 awi_lock(struct awi_softc
*sc
)
1662 * Though driver ioctl should be called with context,
1663 * KAME ipv6 stack calls ioctl in interrupt for now.
1664 * We simply abort the request if there are other
1665 * ioctl requests in progress.
1668 if (!device_is_active(&sc
->sc_dev
))
1673 sc
->sc_cansleep
= 0;
1676 while (sc
->sc_busy
) {
1677 if (!device_is_active(&sc
->sc_dev
))
1680 error
= tsleep(sc
, PWAIT
| PCATCH
, "awilck", 0);
1686 sc
->sc_cansleep
= 1;
1691 awi_unlock(struct awi_softc
*sc
)
1694 sc
->sc_cansleep
= 0;
1695 if (sc
->sc_sleep_cnt
)
1700 awi_intr_lock(struct awi_softc
*sc
)
1706 for (retry
= 0; retry
< 10; retry
++) {
1707 for (i
= 0; i
< AWI_LOCKOUT_TIMEOUT
*1000/5; i
++) {
1708 if ((status
= awi_read_1(sc
, AWI_LOCKOUT_HOST
)) == 0)
1714 awi_write_1(sc
, AWI_LOCKOUT_MAC
, 1);
1715 if ((status
= awi_read_1(sc
, AWI_LOCKOUT_HOST
)) == 0)
1717 awi_write_1(sc
, AWI_LOCKOUT_MAC
, 0);
1720 printf("%s: failed to lock interrupt\n",
1721 sc
->sc_if
.if_xname
);
1728 awi_intr_unlock(struct awi_softc
*sc
)
1731 awi_write_1(sc
, AWI_LOCKOUT_MAC
, 0);
1735 awi_newstate(struct ieee80211com
*ic
, enum ieee80211_state nstate
, int arg
)
1737 struct ifnet
*ifp
= ic
->ic_ifp
;
1738 struct awi_softc
*sc
= ifp
->if_softc
;
1739 struct ieee80211_node
*ni
;
1742 enum ieee80211_state ostate
;
1744 static const char *stname
[] =
1745 { "INIT", "SCAN", "AUTH", "ASSOC", "RUN" };
1746 static const char *substname
[] =
1747 { "NONE", "SCAN_INIT", "SCAN_SETMIB", "SCAN_SCCMD",
1748 "SUB_INIT", "SUB_SETSS", "SUB_SYNC" };
1749 #endif /* AWI_DEBUG */
1751 ostate
= ic
->ic_state
;
1752 DPRINTF(("awi_newstate: %s (%s/%s) -> %s\n", stname
[ostate
],
1753 stname
[sc
->sc_nstate
], substname
[sc
->sc_substate
], stname
[nstate
]));
1757 case IEEE80211_S_INIT
:
1758 awi_drvstate(sc
, AWI_DRV_RESET
);
1760 case IEEE80211_S_SCAN
:
1761 if (ic
->ic_opmode
== IEEE80211_M_IBSS
||
1762 ic
->ic_opmode
== IEEE80211_M_AHDEMO
)
1763 awi_drvstate(sc
, AWI_DRV_ADHSC
);
1765 awi_drvstate(sc
, AWI_DRV_INFSY
);
1767 case IEEE80211_S_AUTH
:
1768 awi_drvstate(sc
, AWI_DRV_INFSY
);
1770 case IEEE80211_S_ASSOC
:
1771 awi_drvstate(sc
, AWI_DRV_INFAUTH
);
1773 case IEEE80211_S_RUN
:
1774 if (ic
->ic_opmode
== IEEE80211_M_IBSS
||
1775 ic
->ic_opmode
== IEEE80211_M_AHDEMO
)
1776 awi_drvstate(sc
, AWI_DRV_ADHSY
);
1778 awi_drvstate(sc
, AWI_DRV_INFASSOC
);
1782 if (nstate
== IEEE80211_S_INIT
) {
1783 sc
->sc_substate
= AWI_ST_NONE
;
1784 ic
->ic_flags
&= ~IEEE80211_F_SIBSS
;
1785 return (*sc
->sc_newstate
)(ic
, nstate
, arg
);
1788 /* state transition */
1789 if (nstate
== IEEE80211_S_SCAN
) {
1791 if (sc
->sc_substate
== AWI_ST_NONE
) {
1792 sc
->sc_nstate
= nstate
; /* next state in transition */
1793 sc
->sc_substate
= AWI_ST_SCAN_INIT
;
1795 switch (sc
->sc_substate
) {
1796 case AWI_ST_SCAN_INIT
:
1797 sc
->sc_substate
= AWI_ST_SCAN_SETMIB
;
1799 case IEEE80211_S_RUN
:
1801 if (ifp
->if_flags
& IFF_DEBUG
)
1802 printf("%s: no recent beacons from %s;"
1805 ether_sprintf(ic
->ic_bss
->ni_bssid
));
1807 case IEEE80211_S_AUTH
:
1808 case IEEE80211_S_ASSOC
:
1809 case IEEE80211_S_INIT
:
1810 ieee80211_begin_scan(ic
, 1);
1812 case IEEE80211_S_SCAN
:
1816 if (ic
->ic_flags
& IEEE80211_F_ASCAN
)
1817 newmode
= AWI_SCAN_ACTIVE
;
1819 newmode
= AWI_SCAN_PASSIVE
;
1820 if (sc
->sc_mib_mgt
.aScan_Mode
!= newmode
) {
1821 sc
->sc_mib_mgt
.aScan_Mode
= newmode
;
1822 if ((error
= awi_mib(sc
, AWI_CMD_SET_MIB
,
1823 AWI_MIB_MGT
, AWI_NOWAIT
)) != 0)
1827 case AWI_ST_SCAN_SETMIB
:
1828 sc
->sc_substate
= AWI_ST_SCAN_SCCMD
;
1829 if (sc
->sc_cmd_inprog
) {
1830 if ((error
= awi_cmd_wait(sc
)) != 0)
1833 sc
->sc_cmd_inprog
= AWI_CMD_SCAN
;
1835 awi_write_2(sc
, AWI_CA_SCAN_DURATION
,
1836 (ic
->ic_flags
& IEEE80211_F_ASCAN
) ?
1837 AWI_ASCAN_DURATION
: AWI_PSCAN_DURATION
);
1838 if (sc
->sc_mib_phy
.IEEE_PHY_Type
== AWI_PHY_TYPE_FH
) {
1839 awi_write_1(sc
, AWI_CA_SCAN_SET
,
1840 IEEE80211_FH_CHANSET(
1841 ieee80211_chan2ieee(ic
, ni
->ni_chan
)));
1842 awi_write_1(sc
, AWI_CA_SCAN_PATTERN
,
1843 IEEE80211_FH_CHANPAT(
1844 ieee80211_chan2ieee(ic
, ni
->ni_chan
)));
1845 awi_write_1(sc
, AWI_CA_SCAN_IDX
, 1);
1847 awi_write_1(sc
, AWI_CA_SCAN_SET
,
1848 ieee80211_chan2ieee(ic
, ni
->ni_chan
));
1849 awi_write_1(sc
, AWI_CA_SCAN_PATTERN
, 0);
1850 awi_write_1(sc
, AWI_CA_SCAN_IDX
, 0);
1852 awi_write_1(sc
, AWI_CA_SCAN_SUSP
, 0);
1853 sc
->sc_cur_chan
= ieee80211_chan2ieee(ic
, ni
->ni_chan
);
1854 if ((error
= awi_cmd(sc
, AWI_CMD_SCAN
, AWI_NOWAIT
))
1858 case AWI_ST_SCAN_SCCMD
:
1859 ic
->ic_state
= nstate
;
1860 sc
->sc_substate
= AWI_ST_NONE
;
1861 error
= EINPROGRESS
;
1864 DPRINTF(("awi_newstate: unexpected state %s/%s\n",
1865 stname
[nstate
], substname
[sc
->sc_substate
]));
1866 sc
->sc_substate
= AWI_ST_NONE
;
1873 if (ostate
== IEEE80211_S_SCAN
) {
1874 /* set SSID and channel */
1876 if (sc
->sc_substate
== AWI_ST_NONE
) {
1877 sc
->sc_nstate
= nstate
; /* next state in transition */
1878 sc
->sc_substate
= AWI_ST_SUB_INIT
;
1881 switch (sc
->sc_substate
) {
1882 case AWI_ST_SUB_INIT
:
1883 sc
->sc_substate
= AWI_ST_SUB_SETSS
;
1884 IEEE80211_ADDR_COPY(&sc
->sc_mib_mgt
.aCurrent_BSS_ID
,
1886 memset(&sc
->sc_mib_mgt
.aCurrent_ESS_ID
, 0,
1888 sc
->sc_mib_mgt
.aCurrent_ESS_ID
[0] =
1889 IEEE80211_ELEMID_SSID
;
1890 sc
->sc_mib_mgt
.aCurrent_ESS_ID
[1] = ni
->ni_esslen
;
1891 memcpy(&sc
->sc_mib_mgt
.aCurrent_ESS_ID
[2],
1892 ni
->ni_essid
, ni
->ni_esslen
);
1893 LE_WRITE_2(&sc
->sc_mib_mgt
.aBeacon_Period
,
1895 if ((error
= awi_mib(sc
, AWI_CMD_SET_MIB
, AWI_MIB_MGT
,
1899 case AWI_ST_SUB_SETSS
:
1900 sc
->sc_substate
= AWI_ST_SUB_SYNC
;
1901 if (sc
->sc_cmd_inprog
) {
1902 if ((error
= awi_cmd_wait(sc
)) != 0)
1905 sc
->sc_cmd_inprog
= AWI_CMD_SYNC
;
1906 if (sc
->sc_mib_phy
.IEEE_PHY_Type
== AWI_PHY_TYPE_FH
) {
1907 awi_write_1(sc
, AWI_CA_SYNC_SET
,
1908 IEEE80211_FH_CHANSET(
1909 ieee80211_chan2ieee(ic
, ni
->ni_chan
)));
1910 awi_write_1(sc
, AWI_CA_SYNC_PATTERN
,
1911 IEEE80211_FH_CHANPAT(
1912 ieee80211_chan2ieee(ic
, ni
->ni_chan
)));
1913 awi_write_1(sc
, AWI_CA_SYNC_IDX
,
1915 awi_write_2(sc
, AWI_CA_SYNC_DWELL
,
1918 awi_write_1(sc
, AWI_CA_SYNC_SET
,
1919 ieee80211_chan2ieee(ic
, ni
->ni_chan
));
1920 awi_write_1(sc
, AWI_CA_SYNC_PATTERN
, 0);
1921 awi_write_1(sc
, AWI_CA_SYNC_IDX
, 0);
1922 awi_write_2(sc
, AWI_CA_SYNC_DWELL
, 0);
1924 if (ic
->ic_flags
& IEEE80211_F_SIBSS
) {
1925 memset(&ni
->ni_tstamp
, 0,
1926 sizeof(ni
->ni_tstamp
));
1928 awi_write_1(sc
, AWI_CA_SYNC_STARTBSS
, 1);
1930 awi_write_1(sc
, AWI_CA_SYNC_STARTBSS
, 0);
1931 awi_write_2(sc
, AWI_CA_SYNC_MBZ
, 0);
1932 awi_write_bytes(sc
, AWI_CA_SYNC_TIMESTAMP
,
1933 ni
->ni_tstamp
.data
, sizeof(ni
->ni_tstamp
.data
));
1934 awi_write_4(sc
, AWI_CA_SYNC_REFTIME
, ni
->ni_rstamp
);
1935 sc
->sc_cur_chan
= ieee80211_chan2ieee(ic
, ni
->ni_chan
);
1936 if ((error
= awi_cmd(sc
, AWI_CMD_SYNC
, AWI_NOWAIT
))
1940 case AWI_ST_SUB_SYNC
:
1941 sc
->sc_substate
= AWI_ST_NONE
;
1942 if (ic
->ic_flags
& IEEE80211_F_SIBSS
) {
1943 if ((error
= awi_mib(sc
, AWI_CMD_GET_MIB
,
1944 AWI_MIB_MGT
, AWI_WAIT
)) != 0)
1946 IEEE80211_ADDR_COPY(ni
->ni_bssid
,
1947 &sc
->sc_mib_mgt
.aCurrent_BSS_ID
);
1949 if (nstate
== IEEE80211_S_RUN
) {
1950 sc
->sc_rx_timer
= 10;
1957 DPRINTF(("awi_newstate: unexpected state %s/%s\n",
1958 stname
[nstate
], substname
[sc
->sc_substate
]));
1959 sc
->sc_substate
= AWI_ST_NONE
;
1966 sc
->sc_substate
= AWI_ST_NONE
;
1968 return (*sc
->sc_newstate
)(ic
, nstate
, arg
);
1971 if (error
== EINPROGRESS
)
1975 return (*sc
->sc_newstate
)(ic
, nstate
, arg
);
1979 awi_recv_mgmt(struct ieee80211com
*ic
, struct mbuf
*m0
,
1980 struct ieee80211_node
*ni
,
1981 int subtype
, int rssi
, u_int32_t rstamp
)
1983 struct awi_softc
*sc
= ic
->ic_ifp
->if_softc
;
1985 /* probe request is handled by hardware */
1986 if (subtype
== IEEE80211_FC0_SUBTYPE_PROBE_REQ
)
1988 (*sc
->sc_recv_mgmt
)(ic
, m0
, ni
, subtype
, rssi
, rstamp
);
1992 awi_send_mgmt(struct ieee80211com
*ic
, struct ieee80211_node
*ni
,
1995 struct awi_softc
*sc
= ic
->ic_ifp
->if_softc
;
1997 /* probe request is handled by hardware */
1998 if (type
== IEEE80211_FC0_SUBTYPE_PROBE_REQ
)
2000 return (*sc
->sc_send_mgmt
)(ic
, ni
, type
, arg
);
2003 static struct mbuf
*
2004 awi_ether_encap(struct awi_softc
*sc
, struct mbuf
*m
)
2006 struct ieee80211com
*ic
= &sc
->sc_ic
;
2007 struct ieee80211_node
*ni
= ic
->ic_bss
;
2008 struct ether_header
*eh
;
2009 struct ieee80211_frame
*wh
;
2011 if (m
->m_len
< sizeof(struct ether_header
)) {
2012 m
= m_pullup(m
, sizeof(struct ether_header
));
2016 eh
= mtod(m
, struct ether_header
*);
2017 M_PREPEND(m
, sizeof(struct ieee80211_frame
), M_DONTWAIT
);
2020 wh
= mtod(m
, struct ieee80211_frame
*);
2021 wh
->i_fc
[0] = IEEE80211_FC0_VERSION_0
| IEEE80211_FC0_TYPE_DATA
;
2022 *(u_int16_t
*)wh
->i_dur
= 0;
2023 *(u_int16_t
*)wh
->i_seq
=
2024 htole16(ni
->ni_txseqs
[0] << IEEE80211_SEQ_SEQ_SHIFT
);
2026 if (ic
->ic_opmode
== IEEE80211_M_IBSS
||
2027 ic
->ic_opmode
== IEEE80211_M_AHDEMO
) {
2028 wh
->i_fc
[1] = IEEE80211_FC1_DIR_NODS
;
2029 if (sc
->sc_adhoc_ap
)
2030 IEEE80211_ADDR_COPY(wh
->i_addr1
, ni
->ni_macaddr
);
2032 IEEE80211_ADDR_COPY(wh
->i_addr1
, eh
->ether_dhost
);
2033 IEEE80211_ADDR_COPY(wh
->i_addr2
, eh
->ether_shost
);
2034 IEEE80211_ADDR_COPY(wh
->i_addr3
, ni
->ni_bssid
);
2036 wh
->i_fc
[1] = IEEE80211_FC1_DIR_TODS
;
2037 IEEE80211_ADDR_COPY(wh
->i_addr1
, ni
->ni_bssid
);
2038 IEEE80211_ADDR_COPY(wh
->i_addr2
, eh
->ether_shost
);
2039 IEEE80211_ADDR_COPY(wh
->i_addr3
, eh
->ether_dhost
);
2044 static struct mbuf
*
2045 awi_ether_modcap(struct awi_softc
*sc
, struct mbuf
*m
)
2047 struct ieee80211com
*ic
= &sc
->sc_ic
;
2048 struct ether_header eh
;
2049 struct ieee80211_frame wh
;
2052 if (m
->m_len
< sizeof(wh
) + sizeof(eh
)) {
2053 m
= m_pullup(m
, sizeof(wh
) + sizeof(eh
));
2057 memcpy(&wh
, mtod(m
, void *), sizeof(wh
));
2058 if (wh
.i_fc
[0] != (IEEE80211_FC0_VERSION_0
| IEEE80211_FC0_TYPE_DATA
))
2060 memcpy(&eh
, mtod(m
, char *) + sizeof(wh
), sizeof(eh
));
2061 m_adj(m
, sizeof(eh
) - sizeof(*llc
));
2062 if (ic
->ic_opmode
== IEEE80211_M_IBSS
||
2063 ic
->ic_opmode
== IEEE80211_M_AHDEMO
)
2064 IEEE80211_ADDR_COPY(wh
.i_addr2
, eh
.ether_shost
);
2065 memcpy(mtod(m
, void *), &wh
, sizeof(wh
));
2066 llc
= (struct llc
*)(mtod(m
, char *) + sizeof(wh
));
2067 llc
->llc_dsap
= llc
->llc_ssap
= LLC_SNAP_LSAP
;
2068 llc
->llc_control
= LLC_UI
;
2069 llc
->llc_snap
.org_code
[0] = 0;
2070 llc
->llc_snap
.org_code
[1] = 0;
2071 llc
->llc_snap
.org_code
[2] = 0;
2072 llc
->llc_snap
.ether_type
= eh
.ether_type
;