wlan - Update wlan from Adrian / FreeBSD
[dragonfly.git] / sys / dev / netif / iwl / iwl2100.c
CommitLineData
4fa322a1
SZ
1/*
2 * Copyright (c) 2008 The DragonFly Project. All rights reserved.
3 *
4 * This code is derived from software contributed to The DragonFly Project
5 * by Sepherosa Ziehau <sepherosa@gmail.com>
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
17 * 3. Neither the name of The DragonFly Project nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific, prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
4fa322a1
SZ
33 */
34
35#include <sys/param.h>
36#include <sys/bus.h>
37#include <sys/endian.h>
38#include <sys/firmware.h>
39#include <sys/kernel.h>
9db4b353 40#include <sys/interrupt.h>
4fa322a1
SZ
41#include <sys/mbuf.h>
42#include <sys/module.h>
43#include <sys/sysctl.h>
44#include <sys/socket.h>
45#include <sys/sockio.h>
46#include <sys/rman.h>
47
48#include <net/bpf.h>
49#include <net/if.h>
50#include <net/if_arp.h>
51#include <net/ethernet.h>
52#include <net/if_dl.h>
53#include <net/if_media.h>
54#include <net/ifq_var.h>
55#include <net/netmsg2.h>
56
57#include <netproto/802_11/ieee80211_var.h>
58#include <netproto/802_11/ieee80211_radiotap.h>
59
60#include <bus/pci/pcireg.h>
61#include <bus/pci/pcivar.h>
62
63#include "if_iwlvar.h"
64#include "iwl2100reg.h"
65#include "iwl2100var.h"
66
67#define IWL2100_INIT_F_ENABLE 0x1
68#define IWL2100_INIT_F_IBSSCHAN 0x2
69
70#define sc_tx_th sc_u_tx_th.u_tx_th
71#define sc_rx_th sc_u_rx_th.u_rx_th
72
73static void iwl2100_init(void *);
74static int iwl2100_ioctl(struct ifnet *, u_long, caddr_t, struct ucred *);
f0a26983 75static void iwl2100_start(struct ifnet *, struct ifaltq_subque *);
4fa322a1
SZ
76static void iwl2100_watchdog(struct ifnet *);
77static int iwl2100_newstate(struct ieee80211com *, enum ieee80211_state, int);
78static int iwl2100_media_change(struct ifnet *);
79static void iwl2100_media_status(struct ifnet *, struct ifmediareq *);
80static void iwl2100_stop(struct iwl2100_softc *);
81static void iwl2100_restart(struct iwl2100_softc *);
e175c5b6 82static void iwl2100_reinit(struct iwl2100_softc *);
4fa322a1
SZ
83
84static void iwl2100_intr(void *);
4fa322a1
SZ
85static void iwl2100_txeof(struct iwl2100_softc *);
86static void iwl2100_rxeof(struct iwl2100_softc *);
87static void iwl2100_rxeof_status(struct iwl2100_softc *, int);
88static void iwl2100_rxeof_note(struct iwl2100_softc *, int);
89static void iwl2100_rxeof_cmd(struct iwl2100_softc *, int);
90static void iwl2100_rxeof_data(struct iwl2100_softc *, int);
91
92static void iwl2100_init_dispatch(struct netmsg *);
93static void iwl2100_reinit_dispatch(struct netmsg *);
94static void iwl2100_stop_dispatch(struct netmsg *);
95static void iwl2100_newstate_dispatch(struct netmsg *);
96static void iwl2100_scanend_dispatch(struct netmsg *);
97static void iwl2100_restart_dispatch(struct netmsg *);
98static void iwl2100_bmiss_dispatch(struct netmsg *);
99
e175c5b6 100static void iwl2100_stop_callouts(struct iwl2100_softc *);
4fa322a1
SZ
101static void iwl2100_restart_bmiss(void *);
102static void iwl2100_ibss_bssid(void *);
e175c5b6 103static void iwl2100_reinit_callout(void *);
4fa322a1
SZ
104
105static int iwl2100_dma_alloc(device_t);
106static void iwl2100_dma_free(device_t);
107static int iwl2100_dma_mbuf_create(device_t);
108static void iwl2100_dma_mbuf_destroy(device_t, int, int);
109static int iwl2100_init_tx_ring(struct iwl2100_softc *);
110static int iwl2100_init_rx_ring(struct iwl2100_softc *);
111static void iwl2100_free_tx_ring(struct iwl2100_softc *);
112static void iwl2100_free_rx_ring(struct iwl2100_softc *);
113
114static int iwl2100_alloc_cmd(struct iwl2100_softc *);
115static void iwl2100_free_cmd(struct iwl2100_softc *);
116static int iwl2100_wait_cmd(struct iwl2100_softc *);
117
118static void iwl2100_rxdesc_setup(struct iwl2100_softc *, int);
119static int iwl2100_newbuf(struct iwl2100_softc *, int, int);
120static int iwl2100_encap(struct iwl2100_softc *, struct mbuf *);
121
122static void iwl2100_chan_change(struct iwl2100_softc *,
123 const struct ieee80211_channel *);
124
125static int iwl2100_alloc_firmware(struct iwl2100_softc *,
126 enum ieee80211_opmode);
127static void iwl2100_free_firmware(struct iwl2100_softc *);
128static int iwl2100_load_firmware(struct iwl2100_softc *,
129 enum ieee80211_opmode);
130static int iwl2100_load_fw_ucode(struct iwl2100_softc *,
131 const struct iwl2100_firmware *);
132static int iwl2100_load_fw_data(struct iwl2100_softc *,
133 const struct iwl2100_firmware *);
134static int iwl2100_init_firmware(struct iwl2100_softc *);
135
136static int iwl2100_read_ord2(struct iwl2100_softc *, uint32_t,
137 void *, int);
138static uint32_t iwl2100_read_ord1(struct iwl2100_softc *, uint32_t);
139static void iwl2100_write_ord1(struct iwl2100_softc *, uint32_t, uint32_t);
140
141static int iwl2100_reset(struct iwl2100_softc *);
142static int iwl2100_hw_reset(struct iwl2100_softc *);
143static int iwl2100_rfkilled(struct iwl2100_softc *);
144
145static int iwl2100_scan(struct iwl2100_softc *);
146static int iwl2100_auth(struct iwl2100_softc *);
147static int iwl2100_ibss(struct iwl2100_softc *);
148
149static int iwl2100_hw_init(struct iwl2100_softc *, const uint8_t *,
150 const uint8_t *, uint8_t, uint32_t);
151static void iwl2100_hw_stop(struct iwl2100_softc *);
152static int iwl2100_config(struct iwl2100_softc *, const uint8_t *,
153 const uint8_t *, uint8_t, int);
154static int iwl2100_start_scan(struct iwl2100_softc *, uint32_t, uint32_t);
155
156static int iwl2100_config_op(struct iwl2100_softc *, uint32_t);
157static int iwl2100_set_addr(struct iwl2100_softc *, const uint8_t *);
158static int iwl2100_set_opmode(struct iwl2100_softc *,
159 enum ieee80211_opmode);
160static int iwl2100_set_80211(struct iwl2100_softc *);
161static int iwl2100_set_basicrates(struct iwl2100_softc *);
162static int iwl2100_set_txrates(struct iwl2100_softc *);
163static int iwl2100_set_powersave(struct iwl2100_softc *, int);
164static int iwl2100_set_rtsthreshold(struct iwl2100_softc *, uint16_t);
165static int iwl2100_set_bssid(struct iwl2100_softc *, const uint8_t *);
166static int iwl2100_set_essid(struct iwl2100_softc *, const uint8_t *, int);
167static int iwl2100_set_auth_ciphers(struct iwl2100_softc *,
168 enum ieee80211_authmode);
169static int iwl2100_set_wepkey(struct iwl2100_softc *,
170 const struct ieee80211_key *);
171static int iwl2100_set_weptxkey(struct iwl2100_softc *, ieee80211_keyix);
172static int iwl2100_set_privacy(struct iwl2100_softc *, int);
173static int iwl2100_set_chan(struct iwl2100_softc *,
174 const struct ieee80211_channel *);
175static int iwl2100_set_scanopt(struct iwl2100_softc *, uint32_t, uint32_t);
176static int iwl2100_set_scan(struct iwl2100_softc *);
177static int iwl2100_set_optie(struct iwl2100_softc *, void *, uint16_t);
178static int iwl2100_set_bintval(struct iwl2100_softc *, uint16_t);
179static int iwl2100_set_txpower(struct iwl2100_softc *, uint16_t);
180
181static __inline int
182iwl2100_config_done(struct iwl2100_softc *sc)
183{
184 return iwl2100_config_op(sc, IWL2100_CMD_CONF_DONE);
185}
186
187static __inline int
188iwl2100_config_start(struct iwl2100_softc *sc)
189{
190 return iwl2100_config_op(sc, IWL2100_CMD_CONF_START);
191}
192
193static __inline void
194iwl2100_restart_done(struct iwl2100_softc *sc)
195{
196 callout_stop(&sc->sc_restart_bmiss);
197 sc->sc_flags &= ~IWL2100_F_RESTARTING;
198}
199
200int
201iwl2100_attach(device_t dev)
202{
203 struct iwl2100_softc *sc = device_get_softc(dev);
204 struct ieee80211com *ic = &sc->sc_ic;
205 struct ifnet *ifp = &ic->ic_if;
206 uint16_t val;
207 int error, i;
208
209 /*
210 * Linux voodoo:
211 * Clear the retry timeout PCI configuration register to keep
212 * PCI TX retries from interfering with C3 CPU state.
213 */
214 pci_write_config(dev, IWL2100_PCIR_RETRY_TIMEOUT, 0, 1);
215
216 /*
217 * Allocate DMA stuffs
218 */
219 error = iwl2100_dma_alloc(dev);
220 if (error)
221 return error;
222
223 /* Disable interrupts */
224 CSR_WRITE_4(sc, IWL2100_INTR_MASK, 0);
225
226 /*
227 * SW reset before reading EEPROM
228 */
229 error = iwl2100_reset(sc);
230 if (error)
231 return error;
232
233 ifp->if_softc = sc;
234 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
235 ifp->if_init = iwl2100_init;
236 ifp->if_ioctl = iwl2100_ioctl;
237 ifp->if_start = iwl2100_start;
238 ifp->if_watchdog = iwl2100_watchdog;
239 ifq_set_maxlen(&ifp->if_snd, IWL2100_TX_USED_MAX);
c3d41318 240#ifdef notyet
4fa322a1 241 ifq_set_ready(&ifp->if_snd);
c3d41318 242#endif
4fa322a1
SZ
243
244#ifdef DUMP_EEPROM
245 device_printf(dev, "eeprom\n");
246 for (i = 0; i < 128; ++i) {
247 if (i != 0 && i % 8 == 0)
248 kprintf("\n");
249 val = iwl_read_eeprom(&sc->iwlcom, i);
250 kprintf("%04x ", val);
251 }
252 kprintf("\n");
253#endif
254
255 /* IBSS channel mask */
256 sc->sc_ibss_chans = iwl_read_eeprom(&sc->iwlcom,
257 IWL2100_EEPROM_IBSS_CHANS) & IWL2100_CFG_CHANMASK;
258
259 /* BSS channel mask */
260 sc->sc_bss_chans = iwl_read_eeprom(&sc->iwlcom, IWL2100_EEPROM_CHANS);
261
262 /*
263 * Set MAC address
264 */
265 for (i = 0; i < ETHER_ADDR_LEN / 2; ++i) {
266 val = iwl_read_eeprom(&sc->iwlcom, IWL2100_EEPROM_MAC + i);
267 ic->ic_myaddr[i * 2] = val >> 8;
268 ic->ic_myaddr[(i * 2) + 1] = val & 0xff;
269 }
270
271 /*
272 * Set supported channels
273 */
274 for (i = 0; i < 14; ++i) {
275 if (sc->sc_bss_chans & (1 << i)) {
276 int chan = i + 1;
277
278 ic->ic_channels[chan].ic_freq =
279 ieee80211_ieee2mhz(chan, IEEE80211_CHAN_2GHZ);
280 ic->ic_channels[chan].ic_flags = IEEE80211_CHAN_B;
281 }
282 }
283
284 ic->ic_sup_rates[IEEE80211_MODE_11B] = iwl_rateset_11b;
285 ic->ic_phytype = IEEE80211_T_DS;
286 ic->ic_caps = IEEE80211_C_MONITOR |
287 IEEE80211_C_IBSS |
288 IEEE80211_C_SHPREAMBLE |
289 IEEE80211_C_WPA;
290 ic->ic_caps_ext = IEEE80211_CEXT_AUTOSCAN;
291 ic->ic_state = IEEE80211_S_INIT;
292 ic->ic_opmode = IEEE80211_M_STA;
293
294 ieee80211_ifattach(ic);
295
296 /*
297 * ieee80211_frame will be stripped on TX path, so only
298 * extra space needs to be reserved.
299 */
300 ic->ic_headroom = sizeof(struct iwl2100_tx_hdr) -
301 sizeof(struct ieee80211_frame);
302
303 sc->sc_newstate = ic->ic_newstate;
304 ic->ic_newstate = iwl2100_newstate;
305
306 ieee80211_media_init(ic, iwl2100_media_change, iwl2100_media_status);
307
4c77af2d
SZ
308 ifq_set_cpuid(&ifp->if_snd, rman_get_cpuid(sc->sc_irq_res));
309
4fa322a1
SZ
310 error = bus_setup_intr(dev, sc->sc_irq_res, INTR_MPSAFE,
311 iwl2100_intr, sc, &sc->sc_irq_handle,
312 ifp->if_serializer);
313 if (error) {
314 device_printf(dev, "can't setup intr\n");
315 ieee80211_ifdetach(ic);
316 return ENXIO;
317 }
318
319 /*
320 * Attach radio tap
321 */
322 bpfattach_dlt(ifp, DLT_IEEE802_11_RADIO,
323 sizeof(struct ieee80211_frame) + sizeof(sc->sc_tx_th),
324 &sc->sc_drvbpf);
325
326 sc->sc_tx_th_len = roundup(sizeof(sc->sc_tx_th), sizeof(uint32_t));
327 sc->sc_tx_th.wt_ihdr.it_len = htole16(sc->sc_tx_th_len);
328 sc->sc_tx_th.wt_ihdr.it_present = htole32(IWL2100_TX_RADIOTAP_PRESENT);
329
330 sc->sc_rx_th_len = roundup(sizeof(sc->sc_rx_th), sizeof(uint32_t));
331 sc->sc_rx_th.wr_ihdr.it_len = htole16(sc->sc_rx_th_len);
332 sc->sc_rx_th.wr_ihdr.it_present = htole32(IWL2100_RX_RADIOTAP_PRESENT);
333
334 sc->sc_tx_th.wt_chan_flags = sc->sc_rx_th.wr_chan_flags =
335 htole16(IEEE80211_CHAN_B);
336
337 /*
338 * Create worker thread and initialize all necessary messages
339 */
340 iwl_create_thread(&sc->iwlcom, device_get_unit(dev));
341
342 iwlmsg_init(&sc->sc_scanend_msg, &netisr_adone_rport,
343 iwl2100_scanend_dispatch, sc);
344 iwlmsg_init(&sc->sc_restart_msg, &netisr_adone_rport,
345 iwl2100_restart_dispatch, sc);
346 iwlmsg_init(&sc->sc_bmiss_msg, &netisr_adone_rport,
347 iwl2100_bmiss_dispatch, sc);
348 iwlmsg_init(&sc->sc_reinit_msg, &netisr_adone_rport,
349 iwl2100_reinit_dispatch, sc);
350
351 iwlmsg_init(&sc->sc_assoc_msg, &netisr_adone_rport,
352 iwl2100_newstate_dispatch, sc);
353 sc->sc_assoc_msg.iwlm_nstate = IEEE80211_S_ASSOC;
354 sc->sc_assoc_msg.iwlm_arg = -1;
355
356 iwlmsg_init(&sc->sc_run_msg, &netisr_adone_rport,
357 iwl2100_newstate_dispatch, sc);
358 sc->sc_run_msg.iwlm_nstate = IEEE80211_S_RUN;
359 sc->sc_run_msg.iwlm_arg = -1;
360
361 /*
362 * Initialize callouts
363 */
364 callout_init(&sc->sc_restart_bmiss);
365 callout_init(&sc->sc_ibss);
e175c5b6 366 callout_init(&sc->sc_reinit);
4fa322a1
SZ
367
368 /* Add sysctl node */
26595b18
SW
369 SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
370 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
4fa322a1
SZ
371 "debug", CTLFLAG_RW, &sc->sc_debug, 0, "debug flags");
372
373 if (bootverbose)
374 ieee80211_announce(ic);
375 return 0;
376}
377
378void
379iwl2100_detach(device_t dev)
380{
381 struct iwl2100_softc *sc = device_get_softc(dev);
382
383 if (device_is_attached(dev)) {
384 struct ifnet *ifp = &sc->sc_ic.ic_if;
385
386 lwkt_serialize_enter(ifp->if_serializer);
e175c5b6
SZ
387
388 sc->sc_flags |= IWL2100_F_DETACH;
4fa322a1
SZ
389 iwl2100_stop(sc);
390 bus_teardown_intr(dev, sc->sc_irq_res, sc->sc_irq_handle);
391 iwl_destroy_thread(&sc->iwlcom);
e175c5b6 392
4fa322a1
SZ
393 lwkt_serialize_exit(ifp->if_serializer);
394
395 iwl2100_free_firmware(sc);
396
397 bpfdetach(ifp);
398 ieee80211_ifdetach(&sc->sc_ic);
399 }
400 iwl2100_dma_free(dev);
401}
402
403int
404iwl2100_shutdown(device_t dev)
405{
406 struct iwl2100_softc *sc = device_get_softc(dev);
407 struct ifnet *ifp = &sc->sc_ic.ic_if;
408
409 lwkt_serialize_enter(ifp->if_serializer);
410 iwl2100_stop(sc);
411 lwkt_serialize_exit(ifp->if_serializer);
412
413 return 0;
414}
415
416static void
417iwl2100_stop(struct iwl2100_softc *sc)
418{
419 struct iwlmsg msg;
420
421 ASSERT_SERIALIZED(sc->sc_ic.ic_if.if_serializer);
422
e175c5b6
SZ
423 iwl2100_stop_callouts(sc);
424
4fa322a1
SZ
425 iwlmsg_init(&msg, &sc->sc_reply_port, iwl2100_stop_dispatch, sc);
426 lwkt_domsg(&sc->sc_thread_port, &msg.iwlm_nmsg.nm_lmsg, 0);
427}
428
429static void
430iwl2100_stop_dispatch(struct netmsg *nmsg)
431{
432 struct iwlmsg *msg = (struct iwlmsg *)nmsg;
433 struct iwl2100_softc *sc = msg->iwlm_softc;
434
435 ASSERT_SERIALIZED(sc->sc_ic.ic_if.if_serializer);
436
437 ieee80211_new_state(&sc->sc_ic, IEEE80211_S_INIT, -1);
438 iwl2100_hw_stop(sc);
439 lwkt_replymsg(&nmsg->nm_lmsg, 0);
440}
441
442static void
443iwl2100_hw_stop(struct iwl2100_softc *sc)
444{
445 struct ifnet *ifp = &sc->sc_ic.ic_if;
446
447 ASSERT_SERIALIZED(ifp->if_serializer);
448 KKASSERT(curthread == &sc->sc_thread);
449
e175c5b6
SZ
450 callout_stop(&sc->sc_reinit);
451
4fa322a1
SZ
452 /* Disable interrupts */
453 CSR_WRITE_4(sc, IWL2100_INTR_MASK, 0);
454
455 /*
456 * HW and SW reset
457 */
458 iwl2100_hw_reset(sc);
459 iwl2100_reset(sc);
460
461 /*
462 * Free TX/RX rings
463 */
464 iwl2100_free_tx_ring(sc);
465 iwl2100_free_rx_ring(sc);
466
467 /* NOTE: MUST after iwl2100_free_tx_ring() */
468 iwl2100_free_cmd(sc);
469
470 ifp->if_timer = 0;
9ed293e0
SZ
471 ifp->if_flags &= ~IFF_RUNNING;
472 ifq_clr_oactive(&ifp->if_snd);
4fa322a1
SZ
473
474 sc->sc_tx_timer = 0;
475 sc->sc_flags &= ~(IWL2100_F_WAITCMD |
476 IWL2100_F_INITED |
477 IWL2100_F_SCANNING |
478 IWL2100_F_RESTARTING |
479 IWL2100_F_IFSTART |
e175c5b6
SZ
480 IWL2100_F_ERROR |
481 IWL2100_F_ZERO_CMD);
4fa322a1
SZ
482}
483
484static int
485iwl2100_reset(struct iwl2100_softc *sc)
486{
487 int i;
488
489 /*
490 * Software reset
491 */
492#define WAIT_MAX 1000
493
494 CSR_WRITE_4(sc, IWL2100_RESET, IWL2100_RESET_SW);
495 for (i = 0; i < WAIT_MAX; ++i) {
496 DELAY(10);
497 if (CSR_READ_4(sc, IWL2100_RESET) & IWL2100_RESET_DONE)
498 break;
499 }
500 if (i == WAIT_MAX) {
501 if_printf(&sc->sc_ic.ic_if, "sw reset timed out\n");
502 return ETIMEDOUT;
503 }
504
505#undef WAIT_MAX
506
507 /*
508 * Move to D0 state, wait clock to become stable
509 */
510#define WAIT_MAX 10000
511
512 CSR_WRITE_4(sc, IWL2100_CTRL, IWL2100_CTRL_INITDONE);
513 for (i = 0; i < WAIT_MAX; ++i) {
514 DELAY(200);
515 if (CSR_READ_4(sc, IWL2100_CTRL) & IWL2100_CTRL_CLKREADY)
516 break;
517 }
518 if (i == WAIT_MAX) {
519 if_printf(&sc->sc_ic.ic_if, "can't stablize clock\n");
520 return ETIMEDOUT;
521 }
522
523#undef WAIT_MAX
524
525 /*
526 * Move to D0 standby
527 */
528 CSR_SETBITS_4(sc, IWL2100_CTRL, IWL2100_CTRL_STANDBY);
529 return 0;
530}
531
532static int
533iwl2100_dma_alloc(device_t dev)
534{
535 struct iwl2100_softc *sc = device_get_softc(dev);
536 struct iwl2100_tx_ring *tr = &sc->sc_txring;
537 struct iwl2100_rx_ring *rr = &sc->sc_rxring;
538 int error;
539
540 /*
541 * Create top level DMA tag
542 */
543 error = bus_dma_tag_create(NULL, 1, 0,
544 BUS_SPACE_MAXADDR_32BIT,
545 BUS_SPACE_MAXADDR,
546 NULL, NULL,
547 MAXBSIZE,
548 BUS_SPACE_UNRESTRICTED,
549 BUS_SPACE_MAXSIZE_32BIT,
550 0, &sc->sc_dtag);
551 if (error) {
552 device_printf(dev, "can't create DMA tag\n");
553 return error;
554 }
555
556 /*
557 * Create DMA stuffs for TX desc ring
558 */
559 error = iwl_dma_mem_create(dev, sc->sc_dtag, IWL2100_TXRING_SIZE,
560 &tr->tr_dtag, (void **)&tr->tr_desc,
561 &tr->tr_paddr, &tr->tr_dmap);
562 if (error) {
563 device_printf(dev, "can't create DMA memory for "
564 "TX desc ring\n");
565 return error;
566 }
567
568 /*
569 * Create DMA stuffs for RX desc ring
570 */
571 error = iwl_dma_mem_create(dev, sc->sc_dtag, IWL2100_RXRING_SIZE,
572 &rr->rr_dtag, (void **)&rr->rr_desc,
573 &rr->rr_paddr, &rr->rr_dmap);
574 if (error) {
575 device_printf(dev, "can't create DMA memory for "
576 "RX desc ring\n");
577 return error;
578 }
579
580 /*
581 * Create DMA stuffs for RX status ring
582 */
583 error = iwl_dma_mem_create(dev, sc->sc_dtag, IWL2100_RXSTATUS_SIZE,
584 &rr->rr_st_dtag, (void **)&rr->rr_status,
585 &rr->rr_st_paddr, &rr->rr_st_dmap);
586 if (error) {
587 device_printf(dev, "can't create DMA memory for "
588 "RX status ring\n");
589 return error;
590 }
591
592 /*
593 * Create mbuf DMA stuffs
594 */
595 error = iwl2100_dma_mbuf_create(dev);
596 if (error)
597 return error;
598
599 return 0;
600}
601
602static void
603iwl2100_dma_free(device_t dev)
604{
605 struct iwl2100_softc *sc = device_get_softc(dev);
606 struct iwl2100_tx_ring *tr = &sc->sc_txring;
607 struct iwl2100_rx_ring *rr = &sc->sc_rxring;
608
609 /* Free DMA stuffs for TX desc ring */
610 iwl_dma_mem_destroy(tr->tr_dtag, tr->tr_desc, tr->tr_dmap);
611
612 /* Free DMA stuffs for RX desc ring */
613 iwl_dma_mem_destroy(rr->rr_dtag, rr->rr_desc, rr->rr_dmap);
614
615 /* Free DMA stuffs for RX status ring */
616 iwl_dma_mem_destroy(rr->rr_st_dtag, rr->rr_status, rr->rr_st_dmap);
617
618 /* Free DMA stuffs for mbufs */
619 iwl2100_dma_mbuf_destroy(dev, IWL2100_TX_NDESC, IWL2100_RX_NDESC);
620
621 /* Free top level DMA tag */
622 if (sc->sc_dtag != NULL)
623 bus_dma_tag_destroy(sc->sc_dtag);
624}
625
626static int
627iwl2100_dma_mbuf_create(device_t dev)
628{
629 struct iwl2100_softc *sc = device_get_softc(dev);
630 struct iwl2100_tx_ring *tr = &sc->sc_txring;
631 struct iwl2100_rx_ring *rr = &sc->sc_rxring;
632 int i, error;
633
634 /*
635 * Create mbuf DMA tag
636 */
637 error = bus_dma_tag_create(sc->sc_dtag, 1, 0,
638 BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR,
639 NULL, NULL,
640 MCLBYTES, IWL2100_NSEG_MAX,
641 BUS_SPACE_MAXSIZE_32BIT,
642 BUS_DMA_ALLOCNOW, &sc->sc_mbuf_dtag);
643 if (error) {
644 device_printf(dev, "can't create mbuf DMA tag\n");
645 return error;
646 }
647
648 /*
649 * Create spare DMA map for RX mbufs
650 */
651 error = bus_dmamap_create(sc->sc_mbuf_dtag, 0, &rr->rr_tmp_dmap);
652 if (error) {
653 device_printf(dev, "can't create spare mbuf DMA map\n");
654 bus_dma_tag_destroy(sc->sc_mbuf_dtag);
655 sc->sc_mbuf_dtag = NULL;
656 return error;
657 }
658
659 /*
660 * Create DMA maps for RX mbufs
661 */
662 for (i = 0; i < IWL2100_RX_NDESC; ++i) {
663 error = bus_dmamap_create(sc->sc_mbuf_dtag, 0,
664 &rr->rr_buf[i].rb_dmap);
665 if (error) {
666 device_printf(dev, "can't create %d RX mbuf "
667 "for RX ring\n", i);
668 iwl2100_dma_mbuf_destroy(dev, 0, i);
669 return error;
670 }
671 }
672
673 /*
674 * Create DMA maps for TX mbufs
675 */
676 for (i = 0; i < IWL2100_TX_NDESC; ++i) {
677 error = bus_dmamap_create(sc->sc_mbuf_dtag, 0,
678 &tr->tr_buf[i].tb_dmap);
679 if (error) {
680 device_printf(dev, "can't create %d TX mbuf "
681 "DMA map\n", i);
682 iwl2100_dma_mbuf_destroy(dev, i, IWL2100_RX_NDESC);
683 return error;
684 }
685 }
686 return 0;
687}
688
689static void
690iwl2100_dma_mbuf_destroy(device_t dev, int tx_done, int rx_done)
691{
692 struct iwl2100_softc *sc = device_get_softc(dev);
693 struct iwl2100_tx_ring *tr = &sc->sc_txring;
694 struct iwl2100_rx_ring *rr = &sc->sc_rxring;
695 int i;
696
697 if (sc->sc_mbuf_dtag == NULL)
698 return;
699
700 /*
701 * Destroy DMA maps for RX mbufs
702 */
703 for (i = 0; i < rx_done; ++i) {
704 struct iwl2100_rxbuf *rb = &rr->rr_buf[i];
705
ed20d0e3 706 KASSERT(rb->rb_mbuf == NULL, ("RX mbuf is not freed yet"));
4fa322a1
SZ
707 bus_dmamap_destroy(sc->sc_mbuf_dtag, rb->rb_dmap);
708 }
709
710 /*
711 * Destroy DMA maps for TX mbufs
712 */
713 for (i = 0; i < tx_done; ++i) {
714 struct iwl2100_txbuf *tb = &tr->tr_buf[i];
715
ed20d0e3 716 KASSERT(tb->tb_mbuf == NULL, ("TX mbuf is not freed yet"));
4fa322a1
SZ
717 bus_dmamap_destroy(sc->sc_mbuf_dtag, tb->tb_dmap);
718 }
719
720 /*
721 * Destroy spare mbuf DMA map
722 */
723 bus_dmamap_destroy(sc->sc_mbuf_dtag, rr->rr_tmp_dmap);
724
725 /*
726 * Destroy mbuf DMA tag
727 */
728 bus_dma_tag_destroy(sc->sc_mbuf_dtag);
729 sc->sc_mbuf_dtag = NULL;
730}
731
732static void
733iwl2100_init(void *xsc)
734{
735 struct iwl2100_softc *sc = xsc;
736 struct iwlmsg msg;
737
738 ASSERT_SERIALIZED(sc->sc_ic.ic_if.if_serializer);
739
e175c5b6
SZ
740 iwl2100_stop_callouts(sc);
741
4fa322a1
SZ
742 iwlmsg_init(&msg, &sc->sc_reply_port, iwl2100_init_dispatch, sc);
743 lwkt_domsg(&sc->sc_thread_port, &msg.iwlm_nmsg.nm_lmsg, 0);
744}
745
746static void
747iwl2100_init_dispatch(struct netmsg *nmsg)
748{
749 struct iwlmsg *msg = (struct iwlmsg *)nmsg;
750 struct iwl2100_softc *sc = msg->iwlm_softc;
751 struct ieee80211com *ic = &sc->sc_ic;
752 struct ifnet *ifp = &ic->ic_if;
e175c5b6 753 int error = 0, flags;
4fa322a1
SZ
754
755 ASSERT_SERIALIZED(ifp->if_serializer);
756
e175c5b6
SZ
757 if (sc->sc_flags & IWL2100_F_DETACH)
758 goto back;
759
4fa322a1
SZ
760 ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
761
762 if (ic->ic_opmode != IEEE80211_M_MONITOR) {
763 /*
764 * XXX
765 * Workaround for dummy firmware:
766 * Don't enable hardware too early, since
767 * once it is enabled, it will start scanning.
768 */
769 flags = 0;
770 } else {
771 flags = IWL2100_INIT_F_ENABLE;
772 }
773
774 /* Always put the device into a known state */
775 error = iwl2100_hw_init(sc, NULL,
776 ic->ic_des_essid, ic->ic_des_esslen, flags);
777 if (error)
778 goto back;
779
e175c5b6
SZ
780 if (sc->sc_flags & IWL2100_F_ZERO_CMD) {
781 if_printf(ifp, "zero cmd, reinit 1s later\n");
782 iwl2100_hw_stop(sc);
783
784 callout_reset(&sc->sc_reinit, hz, iwl2100_reinit_callout, sc);
785 goto back;
786 }
787
4fa322a1
SZ
788 if (ic->ic_opmode != IEEE80211_M_MONITOR) {
789 if (ic->ic_roaming != IEEE80211_ROAMING_MANUAL)
790 ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
791 } else {
792 ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
793 }
794back:
795 if (error)
796 iwl2100_stop(sc);
797 lwkt_replymsg(&nmsg->nm_lmsg, error);
798}
799
800static int
801iwl2100_ioctl(struct ifnet *ifp, u_long cmd, caddr_t req, struct ucred *cr)
802{
803 struct iwl2100_softc *sc = ifp->if_softc;
804 int error = 0;
805
806 ASSERT_SERIALIZED(ifp->if_serializer);
807
e175c5b6
SZ
808 if (sc->sc_flags & IWL2100_F_DETACH)
809 return 0;
810
4fa322a1
SZ
811 switch (cmd) {
812 case SIOCSIFFLAGS:
813 if (ifp->if_flags & IFF_UP) {
814 if ((ifp->if_flags & IFF_RUNNING) == 0)
815 iwl2100_init(sc);
816 } else {
e175c5b6 817 if (ifp->if_flags & IFF_RUNNING) {
4fa322a1 818 iwl2100_stop(sc);
e175c5b6
SZ
819 } else {
820 /*
821 * Stop callouts explicitly, since
822 * if reinitialization is happening,
823 * IFF_RUNNING will not be turned on.
824 */
825 iwl2100_stop_callouts(sc);
826 }
4fa322a1
SZ
827 }
828 break;
829 default:
830 error = ieee80211_ioctl(&sc->sc_ic, cmd, req, cr);
831 break;
832 }
833
834 if (error == ENETRESET) {
835 if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) ==
836 (IFF_UP | IFF_RUNNING))
837 iwl2100_init(sc);
838 error = 0;
839 }
840 return error;
841}
842
843static void
f0a26983 844iwl2100_start(struct ifnet *ifp, struct ifaltq_subque *ifsq)
4fa322a1
SZ
845{
846 struct iwl2100_softc *sc = ifp->if_softc;
847 struct ieee80211com *ic = &sc->sc_ic;
848 struct iwl2100_tx_ring *tr = &sc->sc_txring;
849 int trans = 0;
850
f0a26983 851 ASSERT_ALTQ_SQ_DEFAULT(ifp, ifsq);
4fa322a1
SZ
852 ASSERT_SERIALIZED(ifp->if_serializer);
853
9db4b353
SZ
854 if (sc->sc_flags & IWL2100_F_DETACH) {
855 ieee80211_drain_mgtq(&ic->ic_mgtq);
856 ifq_purge(&ifp->if_snd);
e175c5b6 857 return;
9db4b353 858 }
e175c5b6 859
9ed293e0 860 if ((ifp->if_flags & IFF_RUNNING) == 0 || ifq_is_oactive(&ifp->if_snd))
4fa322a1
SZ
861 return;
862
9db4b353
SZ
863 if ((sc->sc_flags & IWL2100_F_IFSTART) == 0) {
864 ifq_purge(&ifp->if_snd);
4fa322a1 865 goto back;
9db4b353 866 }
4fa322a1
SZ
867
868 while (tr->tr_used < IWL2100_TX_USED_MAX) {
869 struct ieee80211_frame *wh;
870 struct ieee80211_node *ni;
871 struct ether_header *eh;
872 struct mbuf *m;
873
ac9843a1 874 m = ifq_dequeue(&ifp->if_snd);
4fa322a1
SZ
875 if (m == NULL)
876 break;
877
878 if (m->m_len < sizeof(*eh)) {
879 m = m_pullup(m, sizeof(*eh));
880 if (m == NULL) {
d40991ef 881 IFNET_STAT_INC(ifp, oerrors, 1);
4fa322a1
SZ
882 continue;
883 }
884 }
885 eh = mtod(m, struct ether_header *);
886
887 ni = ieee80211_find_txnode(ic, eh->ether_dhost);
888 if (ni == NULL) {
889 m_freem(m);
d40991ef 890 IFNET_STAT_INC(ifp, oerrors, 1);
4fa322a1
SZ
891 continue;
892 }
893
894 /* TODO: PS */
895
896 BPF_MTAP(ifp, m);
897
898 m = ieee80211_encap(ic, m, ni);
899 if (m == NULL) {
900 ieee80211_free_node(ni);
d40991ef 901 IFNET_STAT_INC(ifp, oerrors, 1);
4fa322a1
SZ
902 continue;
903 }
904
905 if (ic->ic_rawbpf != NULL)
906 bpf_mtap(ic->ic_rawbpf, m);
907
908 wh = mtod(m, struct ieee80211_frame *);
085ff963 909 if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
4fa322a1
SZ
910 if (ieee80211_crypto_encap(ic, ni, m) == NULL) {
911 ieee80211_free_node(ni);
912 m_freem(m);
d40991ef 913 IFNET_STAT_INC(ifp, oerrors, 1);
4fa322a1
SZ
914 continue;
915 }
916 }
917
918 /*
919 * TX radio tap
920 */
921 if (sc->sc_drvbpf != NULL) {
085ff963 922 if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED)
4fa322a1
SZ
923 sc->sc_tx_th.wt_flags = IEEE80211_RADIOTAP_F_WEP;
924 else
925 sc->sc_tx_th.wt_flags = 0;
926 bpf_ptap(sc->sc_drvbpf, m, &sc->sc_tx_th,
927 sc->sc_tx_th_len);
928 }
929 wh = NULL; /* Catch any invalid use */
930
931 ieee80211_free_node(ni);
932
933 if (iwl2100_encap(sc, m)) {
d40991ef 934 IFNET_STAT_INC(ifp, oerrors, 1);
4fa322a1
SZ
935 continue;
936 }
937
d40991ef 938 IFNET_STAT_INC(ifp, opackets, 1);
4fa322a1
SZ
939 trans = 1;
940 }
941
942 if (tr->tr_used >= IWL2100_TX_USED_MAX)
9ed293e0 943 ifq_set_oactive(&ifp->if_snd);
4fa322a1
SZ
944
945 if (trans) {
946 bus_dmamap_sync(tr->tr_dtag, tr->tr_dmap, BUS_DMASYNC_PREWRITE);
947 CSR_WRITE_4(sc, IWL2100_TXQ_WRITE_IDX, tr->tr_index);
948 sc->sc_tx_timer = 5;
949 }
950back:
951 ieee80211_drain_mgtq(&ic->ic_mgtq);
952 ifp->if_timer = 1;
953}
954
955static void
956iwl2100_watchdog(struct ifnet *ifp)
957{
958 struct iwl2100_softc *sc = ifp->if_softc;
959
960 ASSERT_SERIALIZED(ifp->if_serializer);
961
e175c5b6
SZ
962 if (sc->sc_flags & IWL2100_F_DETACH)
963 return;
964
4fa322a1
SZ
965 if (sc->sc_tx_timer) {
966 if (--sc->sc_tx_timer == 0) {
967 if_printf(ifp, "watchdog timeout!\n");
d40991ef 968 IFNET_STAT_INC(ifp, oerrors, 1);
4fa322a1
SZ
969 iwl2100_restart(sc);
970 return;
971 } else {
972 ifp->if_timer = 1;
973 }
974 }
975 ieee80211_watchdog(&sc->sc_ic);
976}
977
978static int
979iwl2100_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
980{
981 struct ifnet *ifp = &ic->ic_if;
982 struct iwl2100_softc *sc = ifp->if_softc;
983 struct iwlmsg msg;
984
985 ASSERT_SERIALIZED(ifp->if_serializer);
986
987 iwlmsg_init(&msg, &sc->sc_reply_port, iwl2100_newstate_dispatch, sc);
988 msg.iwlm_nstate = nstate;
989 msg.iwlm_arg = arg;
990
991 return lwkt_domsg(&sc->sc_thread_port, &msg.iwlm_nmsg.nm_lmsg, 0);
992}
993
994static void
995iwl2100_newstate_dispatch(struct netmsg *nmsg)
996{
997 struct iwlmsg *msg = (struct iwlmsg *)nmsg;
998 struct iwl2100_softc *sc = msg->iwlm_softc;
999 struct ieee80211com *ic = &sc->sc_ic;
9db4b353 1000#ifdef INVARIANTS
4fa322a1 1001 struct ifnet *ifp = &ic->ic_if;
9db4b353 1002#endif
4fa322a1
SZ
1003 enum ieee80211_state nstate, ostate;
1004 int arg = msg->iwlm_arg, error = 0;
1005
1006 ASSERT_SERIALIZED(ifp->if_serializer);
1007
1008 nstate = msg->iwlm_nstate;
1009 ostate = ic->ic_state;
1010
1011 sc->sc_flags &= ~IWL2100_F_IFSTART;
1012 sc->sc_state_age++;
1013
1014 iwl2100_chan_change(sc, ic->ic_curchan);
1015
1016 callout_stop(&sc->sc_ibss);
1017 iwl2100_restart_done(sc);
1018
1019 if (nstate == IEEE80211_S_INIT)
1020 goto back;
1021
e175c5b6
SZ
1022 if (sc->sc_flags & IWL2100_F_DETACH) {
1023 /*
1024 * Except for INIT, we skip rest of the
1025 * state changes during detaching
1026 */
1027 goto reply;
1028 }
1029
4fa322a1
SZ
1030 if (ic->ic_opmode == IEEE80211_M_STA) {
1031 if (nstate == IEEE80211_S_AUTH)
1032 error = iwl2100_auth(sc);
1033 else if (nstate == IEEE80211_S_RUN)
1034 sc->sc_flags |= IWL2100_F_IFSTART;
1035 } else if (ic->ic_opmode == IEEE80211_M_IBSS) {
1036 if (nstate == IEEE80211_S_RUN) {
1037 DPRINTF(sc, IWL2100_DBG_IBSS, "%s",
1038 "start/join ibss\n");
1039
1040 /*
1041 * IWL2100_F_IFSTART can't be turned on
1042 * until BSSID generated by the firmware
1043 * is extracted.
1044 *
1045 * XXX only if we started the IBSS
1046 */
1047 error = iwl2100_ibss(sc);
1048 }
1049 }
1050back:
1051 if (!error)
1052 error = sc->sc_newstate(ic, nstate, arg);
1053
1054 if (!error) {
1055 if (ic->ic_opmode != IEEE80211_M_MONITOR) {
1056 /*
1057 * Don't use 'nstate' here, since for IBSS
1058 * mode 802.11 layer may enter RUN state in
1059 * a recursive manner, i.e. when we reach
1060 * here, nstate != ic->ic_state
1061 */
1062 if (ic->ic_state == IEEE80211_S_SCAN &&
1063 ic->ic_state != ostate) {
1064 DPRINTF(sc, IWL2100_DBG_SCAN, "%s",
1065 "start scan\n");
1066 error = iwl2100_scan(sc);
1067 }
1068 }
1069 }
e175c5b6 1070reply:
4fa322a1
SZ
1071 lwkt_replymsg(&nmsg->nm_lmsg, error);
1072}
1073
1074static int
1075iwl2100_media_change(struct ifnet *ifp)
1076{
1077 int error;
1078
1079 ASSERT_SERIALIZED(ifp->if_serializer);
1080
1081 error = ieee80211_media_change(ifp);
1082 if (error != ENETRESET)
1083 return error;
1084
1085 if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == (IFF_UP | IFF_RUNNING))
1086 iwl2100_init(ifp->if_softc);
1087 return 0;
1088}
1089
1090static void
1091iwl2100_media_status(struct ifnet *ifp, struct ifmediareq *imr)
1092{
1093 struct iwl2100_softc *sc = ifp->if_softc;
1094
1095 if (sc->sc_flags & IWL2100_F_IFSTART) {
1096 struct ieee80211_node *ni = sc->sc_ic.ic_bss;
1097 uint32_t txrate;
1098 int i, nrates = 4;
1099
1100 txrate = iwl2100_read_ord1(sc, IWL2100_ORD1_TXRATE) & 0xf;
1101 if (ni->ni_rates.rs_nrates < 4)
1102 nrates = ni->ni_rates.rs_nrates;
1103
1104 for (i = 0; i < nrates; ++i) {
1105 if ((1 << i) & txrate)
1106 ni->ni_txrate = i;
1107 }
1108 }
1109 ieee80211_media_status(ifp, imr);
1110}
1111
1112static void
1113iwl2100_intr(void *xsc)
1114{
1115 struct iwl2100_softc *sc = xsc;
1116 struct ifnet *ifp = &sc->sc_ic.ic_if;
1117 uint32_t intr_status;
1118
1119 ASSERT_SERIALIZED(ifp->if_serializer);
1120
1121 if ((sc->sc_flags & IWL2100_F_INITED) == 0)
1122 return;
1123
1124 intr_status = CSR_READ_4(sc, IWL2100_INTR_STATUS);
1125 if (intr_status == 0xffffffff) /* not for us */
1126 return;
1127
1128 if ((intr_status & IWL2100_INTRS) == 0) /* not interested */
1129 return;
1130
1131 sc->sc_flags |= IWL2100_F_IN_INTR;
1132
1133 /* Disable interrupts */
1134 CSR_WRITE_4(sc, IWL2100_INTR_MASK, 0);
1135
1136 if (intr_status & IWL2100_INTR_EFATAL) {
e175c5b6
SZ
1137 uint32_t error_info;
1138
4fa322a1
SZ
1139 if_printf(ifp, "intr fatal error\n");
1140 CSR_WRITE_4(sc, IWL2100_INTR_STATUS, IWL2100_INTR_EFATAL);
e175c5b6
SZ
1141
1142 error_info = IND_READ_4(sc, IWL2100_IND_ERROR_INFO);
1143 IND_READ_4(sc, error_info & IWL2100_IND_ERRORADDR_MASK);
1144
1145 callout_stop(&sc->sc_reinit);
1146 iwl2100_reinit(sc);
4fa322a1
SZ
1147
1148 /* Leave interrupts disabled */
1149 goto back;
1150 }
1151
1152 if (intr_status & IWL2100_INTR_EPARITY) {
1153 if_printf(ifp, "intr parity error\n");
1154 CSR_WRITE_4(sc, IWL2100_INTR_STATUS, IWL2100_INTR_EPARITY);
1155 }
1156
1157 if (intr_status & IWL2100_INTR_RX) {
1158 CSR_WRITE_4(sc, IWL2100_INTR_STATUS, IWL2100_INTR_RX);
1159 iwl2100_rxeof(sc);
1160 iwl2100_txeof(sc);
1161 }
1162
1163 if (intr_status & IWL2100_INTR_TX) {
1164 CSR_WRITE_4(sc, IWL2100_INTR_STATUS, IWL2100_INTR_TX);
1165 iwl2100_txeof(sc);
1166 }
1167
1168 if (intr_status & IWL2100_INTR_FW_INITED)
1169 CSR_WRITE_4(sc, IWL2100_INTR_STATUS, IWL2100_INTR_FW_INITED);
1170 if (intr_status & IWL2100_INTR_CMD_DONE)
1171 CSR_WRITE_4(sc, IWL2100_INTR_STATUS, IWL2100_INTR_CMD_DONE);
1172
1173 /* Enable interrupts */
1174 CSR_WRITE_4(sc, IWL2100_INTR_MASK, IWL2100_INTRS);
1175back:
1176 sc->sc_flags &= ~IWL2100_F_IN_INTR;
1177}
1178
1179static int
1180iwl2100_hw_reset(struct iwl2100_softc *sc)
1181{
1182 int i;
1183
1184 /*
1185 * Initialize GPIO:
1186 * - Enable GPIO3
1187 * - Make GPIO3 firmware writable
1188 * - Enable GPIO1
1189 * - Turn off LED
1190 */
1191 CSR_WRITE_4(sc, IWL2100_GPIO,
1192 IWL2100_GPIO_3_EN | IWL2100_GPIO_3_FWWR |
1193 IWL2100_GPIO_1_EN | IWL2100_GPIO_LEDOFF);
1194
1195 /*
1196 * Stop master
1197 */
1198#define WAIT_MAX 5
1199
1200 CSR_WRITE_4(sc, IWL2100_RESET, IWL2100_RESET_STOP_MASTER);
1201 for (i = 0; i < WAIT_MAX; ++i) {
1202 DELAY(10);
1203
1204 if (CSR_READ_4(sc, IWL2100_RESET) &
1205 IWL2100_RESET_MASTER_STOPPED)
1206 break;
1207 }
1208 if (i == WAIT_MAX) {
1209 if_printf(&sc->sc_ic.ic_if, "can't stop master\n");
1210 return ETIMEDOUT;
1211 }
1212
1213#undef WAIT_MAX
1214
1215 CSR_WRITE_4(sc, IWL2100_RESET, IWL2100_RESET_SW);
1216 return 0;
1217}
1218
1219static int
1220iwl2100_alloc_firmware(struct iwl2100_softc *sc, enum ieee80211_opmode opmode)
1221{
1222 struct {
1223 const char *suffix;
1224 uint16_t mode;
1225 enum ieee80211_opmode opmode;
1226 struct iwl2100_firmware *fw;
1227 } fw_arr[] = {
1228 { "", IWL2100_FW_M_STA, IEEE80211_M_STA,
1229 &sc->sc_fw_sta },
1230 { "-i", IWL2100_FW_M_IBSS, IEEE80211_M_IBSS,
1231 &sc->sc_fw_ibss },
1232 { "-p", IWL2100_FW_M_MONITOR, IEEE80211_M_MONITOR,
1233 &sc->sc_fw_monitor },
1234 { NULL, 0, 0, NULL }
1235 };
1236 struct ifnet *ifp = &sc->sc_ic.ic_if;
1237 const struct iwl2100_fwimg_hdr *hdr;
12537350 1238 struct iwl2100_firmware *fw = NULL;
4fa322a1
SZ
1239 struct fw_image *image;
1240 char filename[128];
1241 int i, error;
1242
1243 for (i = 0; fw_arr[i].fw != NULL; ++i) {
1244 fw = fw_arr[i].fw;
1245
1246 if (fw_arr[i].opmode == opmode) {
1247 if (fw->fw_image != NULL)
1248 return 0;
1249 else
1250 break;
1251 }
1252 }
ed20d0e3 1253 KASSERT(fw_arr[i].fw != NULL, ("unsupported opmode %u", opmode));
4fa322a1
SZ
1254
1255 ksnprintf(filename, sizeof(filename), IWL2100_FW_PATH,
1256 fw_arr[i].suffix);
1257
1258 /*
1259 * Release the serializer to avoid possible dead lock
1260 */
1261 lwkt_serialize_exit(ifp->if_serializer);
1262 image = firmware_image_load(filename, NULL);
1263 lwkt_serialize_enter(ifp->if_serializer);
1264
1265 if (image == NULL)
1266 return ENOENT;
1267 fw->fw_image = image;
1268
1269 /*
1270 * Verify the image
1271 */
1272 error = EINVAL;
1273
1274 hdr = (const struct iwl2100_fwimg_hdr *)image->fw_image;
1275 if ((hdr->version & 0xff) != 1) {
1276 if_printf(ifp, "%s unsupported firmware version %d",
1277 image->fw_name, hdr->version & 0xff);
1278 goto back;
1279 }
1280
1281 if (hdr->mode != fw_arr[i].mode) {
1282 if_printf(ifp, "%s contains %d mode firmware, should be %d\n",
1283 image->fw_name, hdr->mode, fw_arr[i].mode);
1284 goto back;
1285 }
1286
1287 if (hdr->data_size + hdr->ucode_size + sizeof(*hdr) !=
1288 image->fw_imglen) {
bfc09ba0
MD
1289 if_printf(ifp,
1290 "%s size mismatch, %zu/hdr %zu\n",
1291 image->fw_name, fw->fw_image->fw_imglen,
4fa322a1
SZ
1292 hdr->data_size + hdr->ucode_size + sizeof(*hdr));
1293 goto back;
1294 }
1295
1296 fw->fw_data = (const uint8_t *)(hdr + 1);
1297 fw->fw_data_size = hdr->data_size;
1298 fw->fw_ucode = fw->fw_data + fw->fw_data_size;
1299 fw->fw_ucode_size = hdr->ucode_size;
1300 error = 0;
1301back:
1302 if (error) {
1303 firmware_image_unload(fw->fw_image);
1304 bzero(fw, sizeof(*fw));
1305 }
1306 return error;
1307}
1308
1309static void
1310iwl2100_free_firmware(struct iwl2100_softc *sc)
1311{
1312 struct iwl2100_firmware *fw_arr[] =
1313 { &sc->sc_fw_sta, &sc->sc_fw_ibss, &sc->sc_fw_monitor, NULL };
1314 int i;
1315
1316 for (i = 0; fw_arr[i] != NULL; ++i) {
1317 struct iwl2100_firmware *fw = fw_arr[i];
1318
1319 if (fw->fw_image != NULL) {
1320 firmware_image_unload(fw->fw_image);
1321 bzero(fw, sizeof(*fw));
1322 }
1323 }
1324}
1325
1326static int
1327iwl2100_load_firmware(struct iwl2100_softc *sc, enum ieee80211_opmode opmode)
1328{
1329 static const struct {
1330 uint32_t addr;
1331 int size;
1332 } share_mem[] = {
1333 { IWL2100_SHMEM0, IWL2100_SHMEM0_SIZE },
1334 { IWL2100_SHMEM1, IWL2100_SHMEM1_SIZE },
1335 { IWL2100_SHMEM2, IWL2100_SHMEM2_SIZE },
1336 { IWL2100_SHMEM3, IWL2100_SHMEM3_SIZE },
1337 { IWL2100_SHMEM_INTR, IWL2100_SHMEM_INTR_SIZE },
1338 { 0, 0 }
1339 };
1340 const struct iwl2100_firmware *fw = NULL;
1341 int i, error;
1342
1343 /*
1344 * Pick up the firmware image corresponding to
1345 * the current operation mode
1346 */
1347 switch (opmode) {
1348 case IEEE80211_M_STA:
1349 fw = &sc->sc_fw_sta;
1350 break;
1351 case IEEE80211_M_IBSS:
1352 fw = &sc->sc_fw_ibss;
1353 break;
1354 case IEEE80211_M_MONITOR:
1355 fw = &sc->sc_fw_monitor;
1356 break;
1357 default:
ed20d0e3 1358 panic("unsupported opmode %d", opmode);
4fa322a1
SZ
1359 break;
1360 }
1361 KASSERT(fw->fw_image != NULL,
1362 ("opmode %d firmware image is not allocated yet\n", opmode));
1363
1364 /* Load ucode */
1365 error = iwl2100_load_fw_ucode(sc, fw);
1366 if (error)
1367 return error;
1368
1369 /* SW reset */
1370 error = iwl2100_reset(sc);
1371 if (error)
1372 return error;
1373
1374 /* Load data */
1375 error = iwl2100_load_fw_data(sc, fw);
1376 if (error)
1377 return error;
1378
1379 /* Clear shared memory */
1380 for (i = 0; share_mem[i].size != 0; ++i) {
1381 uint32_t addr = share_mem[i].addr;
1382 int j;
1383
1384 for (j = 0; j < share_mem[i].size; j += 4)
1385 IND_WRITE_4(sc, addr + j, 0);
1386 }
1387
1388 return 0;
1389}
1390
1391#define IND_WRITE_FLUSH_2(sc, reg, val) \
1392do { \
1393 IND_WRITE_2((sc), (reg), (val)); \
1394 CSR_READ_4((sc), 0); \
1395} while (0)
1396
1397#define IND_WRITE_FLUSH_1(sc, reg, val) \
1398do { \
1399 IND_WRITE_1((sc), (reg), (val)); \
1400 CSR_READ_4((sc), 0); \
1401} while (0)
1402
1403/* XXX need more comment */
1404static int
1405iwl2100_load_fw_ucode(struct iwl2100_softc *sc,
1406 const struct iwl2100_firmware *fw)
1407{
1408 struct iwl2100_ucode_resp resp;
1409 const uint8_t *p;
1410 int i;
1411
1412 /* Hold ARC */
1413 IND_WRITE_4(sc, IWL2100_IND_HALT, IWL2100_IND_HALT_HOLD);
1414
1415 /* Allow ARC to run */
1416 CSR_WRITE_4(sc, IWL2100_RESET, 0);
1417
1418 IND_WRITE_FLUSH_2(sc, IWL2100_IND_CTRL, 0x703);
1419 IND_WRITE_FLUSH_2(sc, IWL2100_IND_CTRL, 0x707);
1420
1421 IND_WRITE_FLUSH_1(sc, 0x210014, 0x72);
1422 IND_WRITE_FLUSH_1(sc, 0x210014, 0x72);
1423
1424 IND_WRITE_FLUSH_1(sc, 0x210000, 0x40);
1425 IND_WRITE_FLUSH_1(sc, 0x210000, 0);
1426 IND_WRITE_FLUSH_1(sc, 0x210000, 0x40);
1427
1428 p = fw->fw_ucode;
1429 for (i = 0; i < fw->fw_ucode_size; ++i, ++p)
1430 IND_WRITE_1(sc, 0x210010, *p);
1431
1432 IND_WRITE_FLUSH_1(sc, 0x210000, 0);
1433 IND_WRITE_FLUSH_1(sc, 0x210000, 0);
1434 IND_WRITE_FLUSH_1(sc, 0x210000, 0x80);
1435
1436
1437 IND_WRITE_FLUSH_2(sc, IWL2100_IND_CTRL, 0x703);
1438 IND_WRITE_FLUSH_2(sc, IWL2100_IND_CTRL, 0x707);
1439
1440 IND_WRITE_FLUSH_1(sc, 0x210014, 0x72);
1441 IND_WRITE_FLUSH_1(sc, 0x210014, 0x72);
1442
1443 IND_WRITE_FLUSH_1(sc, 0x210000, 0);
1444 IND_WRITE_1(sc, 0x210000, 0x80);
1445
1446#define WAIT_MAX 10
1447 for (i = 0; i < WAIT_MAX; ++i) {
1448 DELAY(10);
1449
1450 if (IND_READ_1(sc, 0x210000) & 0x1)
1451 break;
1452 }
1453 if (i == WAIT_MAX) {
1454 if_printf(&sc->sc_ic.ic_if,
1455 "wait ucode symbol init timed out\n");
1456 return ETIMEDOUT;
1457 }
1458#undef WAIT_MAX
1459
1460#define WAIT_MAX 30
1461 for (i = 0; i < WAIT_MAX; ++i) {
1462 uint16_t *r = (uint16_t *)&resp;
1463 int j;
1464
1465 for (j = 0; j < sizeof(resp) / 2; ++j, ++r)
1466 *r = IND_READ_2(sc, 0x210004);
1467
1468 if (resp.cmd_id == 1 && resp.ucode_valid == 1)
1469 break;
1470 DELAY(10);
1471 }
1472 if (i == WAIT_MAX) {
1473 if_printf(&sc->sc_ic.ic_if,
1474 "wait ucode response timed out\n");
1475 return ETIMEDOUT;
1476 }
1477#undef WAIT_MAX
1478
1479 /* Release ARC */
1480 IND_WRITE_4(sc, IWL2100_IND_HALT, 0);
1481
1482 if (bootverbose) {
1483 if_printf(&sc->sc_ic.ic_if, "ucode rev.%d date %d.%d.20%02d "
1484 "time %02d:%02d\n", resp.ucode_rev,
1485 resp.date_time[0], resp.date_time[1],
1486 resp.date_time[2], resp.date_time[3],
1487 resp.date_time[4]);
1488 }
1489
1490 return 0;
1491}
1492
1493#undef IND_WRITE_FLUSH_1
1494#undef IND_WRITE_FLUSH_2
1495
1496static int
1497iwl2100_load_fw_data(struct iwl2100_softc *sc,
1498 const struct iwl2100_firmware *fw)
1499{
1500 const uint8_t *p = fw->fw_data;
1501 int w = 0;
1502
1503 while (w < fw->fw_data_size) {
1504 const struct iwl2100_fwdata_hdr *h;
1505 int hlen, i;
1506
1507 h = (const struct iwl2100_fwdata_hdr *)p;
1508 if (h->len > 32 || h->len == 0) {
1509 if_printf(&sc->sc_ic.ic_if,
1510 "firmware image data corrupted\n");
1511 return EINVAL;
1512 }
1513 if ((h->addr & 0x3) || (h->len & 0x3)) {
1514 if_printf(&sc->sc_ic.ic_if,
1515 "firmware image data with unaligned "
1516 "address %#x or length %#x\n",
1517 h->addr, h->len);
1518 return EOPNOTSUPP;
1519 }
1520
1521 hlen = sizeof(*h) + h->len - 1;
1522 if (w + hlen > fw->fw_data_size) {
1523 if_printf(&sc->sc_ic.ic_if,
1524 "firmware image data size mismatch\n");
1525 return EINVAL;
1526 }
1527
1528 CSR_WRITE_4(sc, IWL2100_AUTOINC_ADDR, h->addr);
1529 for (i = 0; i < h->len; i += 4) {
1530 CSR_WRITE_4(sc, IWL2100_AUTOINC_DATA,
1531 *(const uint32_t *)&h->data[i]);
1532 }
1533
1534 p += hlen;
1535 w += hlen;
1536 }
1537 KKASSERT(w == fw->fw_data_size);
1538
1539 return 0;
1540}
1541
1542static void
1543iwl2100_free_tx_ring(struct iwl2100_softc *sc)
1544{
1545 struct iwl2100_tx_ring *tr = &sc->sc_txring;
1546 int i;
1547
1548 for (i = 0; i < IWL2100_TX_NDESC; ++i) {
1549 struct iwl2100_txbuf *tb = &tr->tr_buf[i];
1550
1551 if (tb->tb_mbuf != NULL) {
1552 bus_dmamap_unload(sc->sc_mbuf_dtag, tb->tb_dmap);
1553 if (tb->tb_flags & IWL2100_TBF_CMDBUF) {
1554 KKASSERT(tb->tb_mbuf == sc->sc_cmd);
1555 tb->tb_flags &= ~IWL2100_TBF_CMDBUF;
1556 } else {
1557 m_freem(tb->tb_mbuf);
1558 }
1559 tb->tb_mbuf = NULL;
1560 }
1561 }
1562
1563 bzero(tr->tr_desc, IWL2100_TXRING_SIZE);
1564 bus_dmamap_sync(tr->tr_dtag, tr->tr_dmap, BUS_DMASYNC_PREWRITE);
1565
1566 tr->tr_used = 0;
1567 tr->tr_index = 0;
1568 tr->tr_coll = 0;
1569}
1570
1571static void
1572iwl2100_free_rx_ring(struct iwl2100_softc *sc)
1573{
1574 struct iwl2100_rx_ring *rr = &sc->sc_rxring;
1575 int i;
1576
1577 for (i = 0; i < IWL2100_RX_NDESC; ++i) {
1578 struct iwl2100_rxbuf *rb = &rr->rr_buf[i];
1579
1580 if (rb->rb_mbuf != NULL) {
1581 bus_dmamap_unload(sc->sc_mbuf_dtag, rb->rb_dmap);
1582 m_freem(rb->rb_mbuf);
1583 rb->rb_mbuf = NULL;
1584 }
1585 }
1586
1587 bzero(rr->rr_desc, IWL2100_RXRING_SIZE);
1588 bus_dmamap_sync(rr->rr_dtag, rr->rr_dmap, BUS_DMASYNC_PREWRITE);
1589
1590 bzero(rr->rr_status, IWL2100_RXSTATUS_SIZE);
1591 bus_dmamap_sync(rr->rr_st_dtag, rr->rr_st_dmap, BUS_DMASYNC_PREWRITE);
1592
1593 rr->rr_index = 0;
1594}
1595
1596static void
1597iwl2100_free_cmd(struct iwl2100_softc *sc)
1598{
1599 if (sc->sc_cmd != NULL) {
1600 m_freem(sc->sc_cmd);
1601 sc->sc_cmd = NULL;
1602 }
1603}
1604
1605static int
1606iwl2100_init_tx_ring(struct iwl2100_softc *sc)
1607{
1608 struct iwl2100_tx_ring *tr = &sc->sc_txring;
1609
1610 tr->tr_used = 0;
1611 tr->tr_index = 0;
1612 tr->tr_coll = 0;
1613
1614 bzero(tr->tr_desc, IWL2100_TXRING_SIZE);
1615 bus_dmamap_sync(tr->tr_dtag, tr->tr_dmap, BUS_DMASYNC_PREWRITE);
1616
1617 CSR_WRITE_4(sc, IWL2100_TXQ_ADDR, tr->tr_paddr);
1618 CSR_WRITE_4(sc, IWL2100_TXQ_SIZE, IWL2100_TX_NDESC);
1619 CSR_WRITE_4(sc, IWL2100_TXQ_READ_IDX, 0);
1620 CSR_WRITE_4(sc, IWL2100_TXQ_WRITE_IDX, tr->tr_index);
1621
1622 return 0;
1623}
1624
1625static int
1626iwl2100_init_rx_ring(struct iwl2100_softc *sc)
1627{
1628 struct iwl2100_rx_ring *rr = &sc->sc_rxring;
1629 int i, error;
1630
1631 for (i = 0; i < IWL2100_RX_NDESC; ++i) {
1632 error = iwl2100_newbuf(sc, i, 1);
1633 if (error)
1634 return error;
1635 }
1636 bus_dmamap_sync(rr->rr_st_dtag, rr->rr_st_dmap, BUS_DMASYNC_PREWRITE);
1637 bus_dmamap_sync(rr->rr_dtag, rr->rr_dmap, BUS_DMASYNC_PREWRITE);
1638
1639 rr->rr_index = IWL2100_RX_NDESC - 1;
1640
1641 CSR_WRITE_4(sc, IWL2100_RXQ_ADDR, rr->rr_paddr);
1642 CSR_WRITE_4(sc, IWL2100_RXQ_SIZE, IWL2100_RX_NDESC);
1643 CSR_WRITE_4(sc, IWL2100_RXQ_READ_IDX, 0);
1644 CSR_WRITE_4(sc, IWL2100_RXQ_WRITE_IDX, rr->rr_index);
1645
1646 CSR_WRITE_4(sc, IWL2100_RX_STATUS_ADDR, rr->rr_st_paddr);
1647
1648 return 0;
1649}
1650
1651static int
1652iwl2100_alloc_cmd(struct iwl2100_softc *sc)
1653{
1654 KKASSERT(sc->sc_cmd == NULL);
1655
1656 sc->sc_cmd = m_getcl(MB_WAIT, MT_DATA, M_PKTHDR);
1657 if (sc->sc_cmd == NULL)
1658 return ENOBUFS;
1659 return 0;
1660}
1661
1662static int
1663iwl2100_newbuf(struct iwl2100_softc *sc, int buf_idx, int init)
1664{
1665 struct iwl2100_rx_ring *rr = &sc->sc_rxring;
1666 struct iwl2100_rxbuf *rb;
1667 struct iwl_dmamap_ctx ctx;
1668 bus_dma_segment_t seg;
1669 bus_dmamap_t dmap;
1670 struct mbuf *m;
1671 int error;
1672
1673 KKASSERT(buf_idx < IWL2100_RX_NDESC);
1674 rb = &rr->rr_buf[buf_idx];
1675
1676 m = m_getcl(init ? MB_WAIT : MB_DONTWAIT, MT_DATA, M_PKTHDR);
1677 if (m == NULL) {
1678 error = ENOBUFS;
1679
1680 if (init) {
1681 if_printf(&sc->sc_ic.ic_if, "m_getcl failed\n");
1682 return error;
1683 } else {
1684 goto back;
1685 }
1686 }
1687 m->m_len = m->m_pkthdr.len = MCLBYTES;
1688
1689 /*
1690 * Try load RX mbuf into temporary DMA map
1691 */
1692 ctx.nsegs = 1;
1693 ctx.segs = &seg;
1694 error = bus_dmamap_load_mbuf(sc->sc_mbuf_dtag, rr->rr_tmp_dmap, m,
1695 iwl_dma_buf_addr, &ctx,
1696 init ? BUS_DMA_WAITOK : BUS_DMA_NOWAIT);
1697 if (error || ctx.nsegs == 0) {
1698 if (!error) {
1699 bus_dmamap_unload(sc->sc_mbuf_dtag, rr->rr_tmp_dmap);
1700 error = EFBIG;
1701 if_printf(&sc->sc_ic.ic_if, "too many segments?!\n");
1702 }
1703 m_freem(m);
1704
1705 if (init) {
1706 if_printf(&sc->sc_ic.ic_if, "can't load RX mbuf\n");
1707 return error;
1708 } else {
1709 goto back;
1710 }
1711 }
1712
1713 if (!init)
1714 bus_dmamap_unload(sc->sc_mbuf_dtag, rb->rb_dmap);
1715 rb->rb_mbuf = m;
1716 rb->rb_paddr = seg.ds_addr;
1717
1718 /*
1719 * Swap RX buf's DMA map with the loaded temporary one
1720 */
1721 dmap = rb->rb_dmap;
1722 rb->rb_dmap = rr->rr_tmp_dmap;
1723 rr->rr_tmp_dmap = dmap;
1724
1725 error = 0;
1726back:
1727 iwl2100_rxdesc_setup(sc, buf_idx);
1728 return error;
1729}
1730
1731static void
1732iwl2100_rxdesc_setup(struct iwl2100_softc *sc, int buf_idx)
1733{
1734 struct iwl2100_rx_ring *rr = &sc->sc_rxring;
1735 struct iwl2100_rxbuf *rb;
1736 struct iwl2100_desc *d;
1737 struct iwl2100_rx_status *st;
1738
1739 KKASSERT(buf_idx < IWL2100_RX_NDESC);
1740 rb = &rr->rr_buf[buf_idx];
1741
1742 st = &rr->rr_status[buf_idx];
1743 bzero(st, sizeof(*st));
1744
1745 d = &rr->rr_desc[buf_idx];
1746 bzero(d, sizeof(*d));
1747 d->d_paddr = rb->rb_paddr;
1748 d->d_len = MCLBYTES;
1749}
1750
1751static int
1752iwl2100_init_firmware(struct iwl2100_softc *sc)
1753{
9db4b353 1754#ifdef INVARIANTS
4fa322a1 1755 struct ifnet *ifp = &sc->sc_ic.ic_if;
9db4b353 1756#endif
4fa322a1
SZ
1757 uint32_t intr;
1758 int i;
1759
1760 ASSERT_SERIALIZED(ifp->if_serializer);
1761
1762 CSR_WRITE_4(sc, IWL2100_GPIO,
1763 IWL2100_GPIO_3_EN | IWL2100_GPIO_3_FWWR |
1764 IWL2100_GPIO_1_EN | IWL2100_GPIO_LEDOFF);
1765 CSR_WRITE_4(sc, IWL2100_RESET, 0);
1766
1767 /*
1768 * Wait for firmware to be initialized
1769 */
1770#define WAIT_MAX 5000
1771
1772 for (i = 0; i < WAIT_MAX; ++i) {
1773 DELAY(8000);
1774
1775 intr = CSR_READ_4(sc, IWL2100_INTR_STATUS);
1776 if (intr & IWL2100_INTR_FW_INITED) {
1777 CSR_WRITE_4(sc, IWL2100_INTR_STATUS,
1778 IWL2100_INTR_FW_INITED);
1779 break;
1780 }
1781 if (intr & (IWL2100_INTR_EFATAL | IWL2100_INTR_EPARITY)) {
1782 CSR_WRITE_4(sc, IWL2100_INTR_STATUS,
1783 IWL2100_INTR_EFATAL | IWL2100_INTR_EPARITY);
1784 }
1785 }
1786
1787 intr = CSR_READ_4(sc, IWL2100_INTR_STATUS) & IWL2100_INTRS;
1788 if (intr & CSR_READ_4(sc, IWL2100_INTR_MASK))
1789 CSR_WRITE_4(sc, IWL2100_INTR_STATUS, intr);
1790
1791 if (i == WAIT_MAX) {
1792 if_printf(&sc->sc_ic.ic_if,
1793 "firmware initialization timed out\n");
1794 return ETIMEDOUT;
1795 }
1796
1797#undef WAIT_MAX
1798
1799 /* Enable GPIO1/3 and allow firmware to write to them */
1800 CSR_SETBITS_4(sc, IWL2100_GPIO,
1801 IWL2100_GPIO_1_EN | IWL2100_GPIO_1_FWWR |
1802 IWL2100_GPIO_3_EN | IWL2100_GPIO_3_FWWR);
1803 return 0;
1804}
1805
1806static int
1807iwl2100_read_ord2(struct iwl2100_softc *sc, uint32_t ofs, void *buf0, int buflen)
1808{
1809 uint8_t *buf = buf0;
1810 uint32_t addr, info;
1811 int i, len, ret;
1812
1813#define IND_ALIGN 4
1814#define IND_ALIGN_MASK 0x3
1815
1816 addr = IND_READ_4(sc, sc->sc_ord2 + (ofs << 3));
1817 info = IND_READ_4(sc, sc->sc_ord2 + (ofs << 3) + sizeof(addr));
1818
1819 len = info & 0xffff;
1820 i = info >> 16;
1821
1822 if ((len * i) < buflen)
1823 buflen = len * i;
1824 ret = buflen;
1825
1826 i = addr & IND_ALIGN_MASK;
1827 addr &= ~IND_ALIGN_MASK;
1828 if (i) {
1829 int lim, r;
1830
1831 KKASSERT(i < IND_ALIGN);
1832 if (buflen + i < IND_ALIGN)
1833 lim = buflen + i;
1834 else
1835 lim = IND_ALIGN;
1836 r = lim - i;
1837
1838 CSR_WRITE_4(sc, IWL2100_IND_ADDR, addr);
1839 for (; i < lim; ++i, ++buf)
1840 *buf = CSR_READ_1(sc, IWL2100_IND_DATA + i);
1841
1842 KKASSERT(buflen >= r);
1843 buflen -= r;
1844 if (buflen == 0)
1845 goto back;
1846
1847 addr += IND_ALIGN;
1848 }
1849
1850 len = buflen & ~IND_ALIGN_MASK;
1851 buflen &= IND_ALIGN_MASK;
1852
1853 if (len) {
1854 CSR_WRITE_4(sc, IWL2100_AUTOINC_ADDR, addr);
1855 for (i = 0; i < len; i += 4, addr += 4, buf += 4) {
1856 *((uint32_t *)buf) =
1857 CSR_READ_4(sc, IWL2100_AUTOINC_DATA);
1858 }
1859 }
1860 if (buflen) {
1861 CSR_WRITE_4(sc, IWL2100_IND_ADDR, addr);
1862 for (i = 0; i < buflen; ++i, ++buf)
1863 *buf = CSR_READ_1(sc, IWL2100_IND_DATA + i);
1864 }
1865back:
1866 return ret;
1867
1868#undef IND_ALIGN
1869#undef IND_ALIGN_MASK
1870}
1871
1872static uint32_t
1873iwl2100_read_ord1(struct iwl2100_softc *sc, uint32_t ofs)
1874{
1875 uint32_t addr;
1876
1877 addr = IND_READ_4(sc, sc->sc_ord1 + (ofs << 2));
1878 return IND_READ_4(sc, addr);
1879}
1880
1881static void
1882iwl2100_write_ord1(struct iwl2100_softc *sc, uint32_t ofs, uint32_t val)
1883{
1884 uint32_t addr;
1885
1886 addr = IND_READ_4(sc, sc->sc_ord1 + (ofs << 2));
1887 IND_WRITE_4(sc, addr, val);
1888}
1889
1890static int
1891iwl2100_rfkilled(struct iwl2100_softc *sc)
1892{
1893 int i;
1894
1895 if ((sc->sc_caps & IWL2100_C_RFKILL) == 0)
1896 return 0;
1897
1898#define TEST_MAX 5
1899
1900 for (i = 0; i < TEST_MAX; ++i) {
1901 DELAY(40);
1902
1903 if (CSR_READ_4(sc, IWL2100_GPIO) & IWL2100_GPIO_RFKILLED)
1904 break;
1905 }
1906 if (i != TEST_MAX) {
1907 if_printf(&sc->sc_ic.ic_if, "RF killed\n");
1908 return 1;
1909 }
1910
1911#undef TEST_MAX
1912
1913 return 0;
1914}
1915
1916static int
1917iwl2100_set_addr(struct iwl2100_softc *sc, const uint8_t *eaddr)
1918{
1919 struct iwl2100_cmd *cmd;
1920 int error;
1921
1922 if (sc->sc_flags & IWL2100_F_WAITCMD) {
1923 if_printf(&sc->sc_ic.ic_if, "there is command pending\n");
1924 return EEXIST;
1925 }
1926
1927 cmd = mtod(sc->sc_cmd, struct iwl2100_cmd *);
1928 bzero(cmd, sizeof(*cmd));
1929
1930 cmd->c_cmd = IWL2100_CMD_SET_ADDR;
1931 cmd->c_param_len = IEEE80211_ADDR_LEN;
1932 IEEE80211_ADDR_COPY(cmd->c_param, eaddr);
1933
1934 error = iwl2100_wait_cmd(sc);
1935 if (error) {
1936 if_printf(&sc->sc_ic.ic_if, "%s failed\n", __func__);
1937 return error;
1938 }
1939 return 0;
1940}
1941
1942static int
1943iwl2100_set_opmode(struct iwl2100_softc *sc, enum ieee80211_opmode opmode)
1944{
1945 struct iwl2100_cmd *cmd;
1946 int error;
1947
1948 if (sc->sc_flags & IWL2100_F_WAITCMD) {
1949 if_printf(&sc->sc_ic.ic_if, "there is command pending\n");
1950 return EEXIST;
1951 }
1952
1953 cmd = mtod(sc->sc_cmd, struct iwl2100_cmd *);
8075c3b8 1954 bzero(cmd, sizeof(*cmd));
4fa322a1
SZ
1955
1956 cmd->c_cmd = IWL2100_CMD_SET_OPMODE;
1957 cmd->c_param_len = sizeof(cmd->c_param[0]);
1958 switch (opmode) {
1959 case IEEE80211_M_STA:
1960 cmd->c_param[0] = IWL2100_OPMODE_STA;
1961 break;
1962 case IEEE80211_M_IBSS:
1963 cmd->c_param[0] = IWL2100_OPMODE_IBSS;
1964 break;
1965 case IEEE80211_M_MONITOR:
1966 /* YYY ipw2100 leave this unset */
1967 cmd->c_param[0] = IWL2100_OPMODE_MONITOR;
1968 break;
1969 default:
ed20d0e3 1970 panic("unsupported opmode %d", opmode);
4fa322a1
SZ
1971 break;
1972 }
1973
1974 error = iwl2100_wait_cmd(sc);
1975 if (error) {
1976 if_printf(&sc->sc_ic.ic_if, "%s failed\n", __func__);
1977 return error;
1978 }
1979 return 0;
1980}
1981
1982static int
1983iwl2100_set_80211(struct iwl2100_softc *sc)
1984{
1985 struct ieee80211com *ic = &sc->sc_ic;
1986 struct iwl2100_cmd *cmd;
1987 int error;
1988
1989 if (sc->sc_flags & IWL2100_F_WAITCMD) {
1990 if_printf(&ic->ic_if, "there is command pending\n");
1991 return EEXIST;
1992 }
1993
1994 cmd = mtod(sc->sc_cmd, struct iwl2100_cmd *);
8075c3b8 1995 bzero(cmd, sizeof(*cmd));
4fa322a1
SZ
1996
1997 cmd->c_cmd = IWL2100_CMD_SET_80211;
1998 cmd->c_param_len = sizeof(cmd->c_param[0]) * 3;
1999 cmd->c_param[0] = IWL2100_CFG_IBSS | IWL2100_CFG_STA |
2000 IWL2100_CFG_8021X | IWL2100_CFG_AUTO_PREAMBLE;
2001 if (ic->ic_opmode == IEEE80211_M_IBSS)
2002 cmd->c_param[0] |= IWL2100_CFG_IBSS_AUTO_START;
2003 else if (ic->ic_opmode == IEEE80211_M_MONITOR) /* YYY not ipw2100 */
2004 cmd->c_param[0] |= IWL2100_CFG_MONITOR;
2005 cmd->c_param[1] = IWL2100_CFG_CHANMASK; /* XXX sc->sc_bss_chans */
2006 cmd->c_param[2] = IWL2100_CFG_CHANMASK; /* YYY sc->sc_ibss_chans */
2007
2008 error = iwl2100_wait_cmd(sc);
2009 if (error) {
2010 if_printf(&ic->ic_if, "%s failed\n", __func__);
2011 return error;
2012 }
2013 return 0;
2014}
2015
2016static int
2017iwl2100_set_basicrates(struct iwl2100_softc *sc)
2018{
2019 struct iwl2100_cmd *cmd;
2020 int error;
2021
2022 if (sc->sc_flags & IWL2100_F_WAITCMD) {
2023 if_printf(&sc->sc_ic.ic_if, "there is command pending\n");
2024 return EEXIST;
2025 }
2026
2027 cmd = mtod(sc->sc_cmd, struct iwl2100_cmd *);
8075c3b8 2028 bzero(cmd, sizeof(*cmd));
4fa322a1
SZ
2029
2030 /*
2031 * This configuration does not seem to have any effects
2032 * on probe-req and assoc-req frames.
2033 */
2034 cmd->c_cmd = IWL2100_CMD_SET_BASICRATES;
2035 cmd->c_param_len = sizeof(cmd->c_param[0]);
2036 cmd->c_param[0] = 0x3; /* 1Mbps and 2Mbps. XXX from caller */
2037
2038 error = iwl2100_wait_cmd(sc);
2039 if (error) {
2040 if_printf(&sc->sc_ic.ic_if, "%s failed\n", __func__);
2041 return error;
2042 }
2043 return 0;
2044}
2045
2046static int
2047iwl2100_set_txrates(struct iwl2100_softc *sc)
2048{
2049 struct ieee80211com *ic = &sc->sc_ic;
2050 struct iwl2100_cmd *cmd;
2051 uint32_t rate_mask;
2052 int error;
2053
2054 if (sc->sc_flags & IWL2100_F_WAITCMD) {
2055 if_printf(&ic->ic_if, "there is command pending\n");
2056 return EEXIST;
2057 }
2058
2059 /* Calculate TX rate mask. XXX let caller do this */
2060 if (ic->ic_fixed_rate != IEEE80211_FIXED_RATE_NONE)
2061 rate_mask = 1 << ic->ic_fixed_rate;
2062 else
2063 rate_mask = 0xf; /* all 11b rates */
2064 KKASSERT((rate_mask & ~0xf) == 0);
2065
2066 /*
2067 * Set TX rates
2068 */
2069 cmd = mtod(sc->sc_cmd, struct iwl2100_cmd *);
8075c3b8 2070 bzero(cmd, sizeof(*cmd));
4fa322a1
SZ
2071
2072 cmd->c_cmd = IWL2100_CMD_SET_TXRATES;
2073 cmd->c_param_len = sizeof(cmd->c_param[0]);
2074 cmd->c_param[0] = rate_mask;
2075
2076 error = iwl2100_wait_cmd(sc);
2077 if (error) {
2078 if_printf(&ic->ic_if, "%s failed\n", __func__);
2079 return error;
2080 }
2081
2082 /*
2083 * Set MSDU TX rates
2084 */
2085 cmd = mtod(sc->sc_cmd, struct iwl2100_cmd *);
8075c3b8 2086 bzero(cmd, sizeof(*cmd));
4fa322a1
SZ
2087
2088 cmd->c_cmd = IWL2100_CMD_SET_MSDU_TXRATES;
2089 cmd->c_param_len = sizeof(cmd->c_param[0]);
2090 cmd->c_param[0] = rate_mask;
2091
2092 error = iwl2100_wait_cmd(sc);
2093 if (error) {
2094 if_printf(&ic->ic_if, "%s failed\n", __func__);
2095 return error;
2096 }
2097 return 0;
2098}
2099
2100static int
2101iwl2100_set_powersave(struct iwl2100_softc *sc, int on)
2102{
2103 struct iwl2100_cmd *cmd;
2104 int error;
2105
2106 if (sc->sc_flags & IWL2100_F_WAITCMD) {
2107 if_printf(&sc->sc_ic.ic_if, "there is command pending\n");
2108 return EEXIST;
2109 }
2110
2111 cmd = mtod(sc->sc_cmd, struct iwl2100_cmd *);
8075c3b8 2112 bzero(cmd, sizeof(*cmd));
4fa322a1
SZ
2113
2114 cmd->c_cmd = IWL2100_CMD_SET_POWERSAVE;
2115 cmd->c_param_len = sizeof(cmd->c_param[0]);
2116 cmd->c_param[0] = on; /* XXX power level? */
2117
2118 error = iwl2100_wait_cmd(sc);
2119 if (error) {
2120 if_printf(&sc->sc_ic.ic_if, "%s failed\n", __func__);
2121 return error;
2122 }
2123 return 0;
2124}
2125
2126static int
2127iwl2100_set_rtsthreshold(struct iwl2100_softc *sc, uint16_t rtsthreshold)
2128{
2129 struct iwl2100_cmd *cmd;
2130 int error;
2131
2132 if (sc->sc_flags & IWL2100_F_WAITCMD) {
2133 if_printf(&sc->sc_ic.ic_if, "there is command pending\n");
2134 return EEXIST;
2135 }
2136
2137 cmd = mtod(sc->sc_cmd, struct iwl2100_cmd *);
8075c3b8 2138 bzero(cmd, sizeof(*cmd));
4fa322a1
SZ
2139
2140 cmd->c_cmd = IWL2100_CMD_SET_RTSTHRESHOLD;
2141 cmd->c_param_len = sizeof(cmd->c_param[0]);
2142 if (rtsthreshold == IEEE80211_RTS_MAX) {
2143 /* Disable RTS threshold */
2144 cmd->c_param[0] = IWL2100_RTS_MAX;
2145 } else {
2146 if (rtsthreshold >= IWL2100_RTS_MAX)
2147 rtsthreshold = IWL2100_RTS_MAX - 1;
2148 cmd->c_param[0] = rtsthreshold;
2149 }
2150
2151 error = iwl2100_wait_cmd(sc);
2152 if (error) {
2153 if_printf(&sc->sc_ic.ic_if, "%s failed\n", __func__);
2154 return error;
2155 }
2156 return 0;
2157}
2158
2159static int
2160iwl2100_set_bssid(struct iwl2100_softc *sc, const uint8_t *bssid)
2161{
2162 struct iwl2100_cmd *cmd;
2163 int error;
2164
2165 if (sc->sc_flags & IWL2100_F_WAITCMD) {
2166 if_printf(&sc->sc_ic.ic_if, "there is command pending\n");
2167 return EEXIST;
2168 }
2169
2170 cmd = mtod(sc->sc_cmd, struct iwl2100_cmd *);
8075c3b8 2171 bzero(cmd, sizeof(*cmd));
4fa322a1
SZ
2172
2173 cmd->c_cmd = IWL2100_CMD_SET_BSSID;
2174 if (bssid != NULL) {
2175 cmd->c_param_len = IEEE80211_ADDR_LEN;
2176 IEEE80211_ADDR_COPY(cmd->c_param, bssid);
2177 }
2178
2179 error = iwl2100_wait_cmd(sc);
2180 if (error) {
2181 if_printf(&sc->sc_ic.ic_if, "%s failed\n", __func__);
2182 return error;
2183 }
2184 return 0;
2185}
2186
2187static int
2188iwl2100_set_essid(struct iwl2100_softc *sc, const uint8_t *essid, int essid_len)
2189{
2190 struct iwl2100_cmd *cmd;
2191 int error;
2192
2193 if (sc->sc_flags & IWL2100_F_WAITCMD) {
2194 if_printf(&sc->sc_ic.ic_if, "there is command pending\n");
2195 return EEXIST;
2196 }
2197
2198 cmd = mtod(sc->sc_cmd, struct iwl2100_cmd *);
8075c3b8 2199 bzero(cmd, sizeof(*cmd));
4fa322a1
SZ
2200
2201 cmd->c_cmd = IWL2100_CMD_SET_ESSID;
2202 if (essid != NULL) {
2203 KKASSERT(essid_len <= sizeof(cmd->c_param));
2204 cmd->c_param_len = essid_len;
2205 if (essid_len != 0)
2206 bcopy(essid, cmd->c_param, essid_len);
2207 }
2208
2209 error = iwl2100_wait_cmd(sc);
2210 if (error) {
2211 if_printf(&sc->sc_ic.ic_if, "%s failed\n", __func__);
2212 return error;
2213 }
2214 return 0;
2215}
2216
2217static int
2218iwl2100_set_auth_ciphers(struct iwl2100_softc *sc,
2219 enum ieee80211_authmode authmode)
2220{
2221 struct iwl2100_cmdparam_sec *sec;
2222 struct iwl2100_cmd *cmd;
2223 int error;
2224
2225 if (sc->sc_flags & IWL2100_F_WAITCMD) {
2226 if_printf(&sc->sc_ic.ic_if, "there is command pending\n");
2227 return EEXIST;
2228 }
2229
2230 cmd = mtod(sc->sc_cmd, struct iwl2100_cmd *);
8075c3b8 2231 bzero(cmd, sizeof(*cmd));
4fa322a1
SZ
2232
2233 cmd->c_cmd = IWL2100_CMD_SET_SECURITY;
2234 cmd->c_param_len = sizeof(*sec);
2235 sec = (struct iwl2100_cmdparam_sec *)cmd->c_param;
2236
2237 sec->sec_cipher_mask = IWL2100_CIPHER_NONE |
2238 IWL2100_CIPHER_WEP40 |
2239 IWL2100_CIPHER_TKIP |
2240 IWL2100_CIPHER_CCMP |
2241 IWL2100_CIPHER_WEP104;
2242 if (authmode == IEEE80211_AUTH_SHARED)
2243 sec->sec_authmode = IWL2100_AUTH_SHARED;
2244 else
2245 sec->sec_authmode = IWL2100_AUTH_OPEN;
2246
2247 error = iwl2100_wait_cmd(sc);
2248 if (error) {
2249 if_printf(&sc->sc_ic.ic_if, "%s failed\n", __func__);
2250 return error;
2251 }
2252 return 0;
2253}
2254
2255static int
2256iwl2100_set_wepkey(struct iwl2100_softc *sc, const struct ieee80211_key *k)
2257{
2258 struct iwl2100_cmdparam_wepkey *key;
2259 struct iwl2100_cmd *cmd;
2260 int error;
2261
2262 if (k->wk_keylen > IWL2100_KEYDATA_SIZE)
2263 return E2BIG;
2264
2265 if (sc->sc_flags & IWL2100_F_WAITCMD) {
2266 if_printf(&sc->sc_ic.ic_if, "there is command pending\n");
2267 return EEXIST;
2268 }
2269
2270 cmd = mtod(sc->sc_cmd, struct iwl2100_cmd *);
8075c3b8 2271 bzero(cmd, sizeof(*cmd));
4fa322a1
SZ
2272
2273 cmd->c_cmd = IWL2100_CMD_SET_WEPKEY;
2274 cmd->c_param_len = sizeof(*key);
2275 key = (struct iwl2100_cmdparam_wepkey *)cmd->c_param;
2276 key->key_index = k->wk_keyix;
2277 key->key_len = k->wk_keylen;
2278 bcopy(k->wk_key, key->key_data, key->key_len);
2279
2280 error = iwl2100_wait_cmd(sc);
2281 if (error) {
2282 if_printf(&sc->sc_ic.ic_if, "%s failed\n", __func__);
2283 return error;
2284 }
2285 return 0;
2286}
2287
2288static int
2289iwl2100_set_weptxkey(struct iwl2100_softc *sc, ieee80211_keyix txkey)
2290{
2291 struct iwl2100_cmd *cmd;
2292 int error;
2293
2294 if (sc->sc_flags & IWL2100_F_WAITCMD) {
2295 if_printf(&sc->sc_ic.ic_if, "there is command pending\n");
2296 return EEXIST;
2297 }
2298
2299 cmd = mtod(sc->sc_cmd, struct iwl2100_cmd *);
8075c3b8 2300 bzero(cmd, sizeof(*cmd));
4fa322a1
SZ
2301
2302 cmd->c_cmd = IWL2100_CMD_SET_WEPTXKEY;
2303 cmd->c_param_len = sizeof(cmd->c_param[0]);
2304 cmd->c_param[0] = txkey;
2305
2306 error = iwl2100_wait_cmd(sc);
2307 if (error) {
2308 if_printf(&sc->sc_ic.ic_if, "%s failed\n", __func__);
2309 return error;
2310 }
2311 return 0;
2312}
2313
2314static int
2315iwl2100_set_privacy(struct iwl2100_softc *sc, int on)
2316{
2317 struct iwl2100_cmd *cmd;
2318 int error;
2319
2320 if (sc->sc_flags & IWL2100_F_WAITCMD) {
2321 if_printf(&sc->sc_ic.ic_if, "there is command pending\n");
2322 return EEXIST;
2323 }
2324
2325 cmd = mtod(sc->sc_cmd, struct iwl2100_cmd *);
8075c3b8 2326 bzero(cmd, sizeof(*cmd));
4fa322a1
SZ
2327
2328 cmd->c_cmd = IWL2100_CMD_SET_PRIVACY;
2329 cmd->c_param_len = sizeof(cmd->c_param[0]);
2330 cmd->c_param[0] = on ? IWL2100_PRIVACY_ENABLE : 0;
2331
2332 error = iwl2100_wait_cmd(sc);
2333 if (error) {
2334 if_printf(&sc->sc_ic.ic_if, "%s failed\n", __func__);
2335 return error;
2336 }
2337 return 0;
2338}
2339
2340static int
2341iwl2100_wait_cmd(struct iwl2100_softc *sc)
2342{
2343 struct ifnet *ifp = &sc->sc_ic.ic_if;
2344 struct iwl2100_tx_ring *tr = &sc->sc_txring;
2345 struct mbuf *m = sc->sc_cmd;
2346 struct iwl_dmamap_ctx ctx;
2347 bus_dma_segment_t seg;
2348 struct iwl2100_desc *d;
2349 struct iwl2100_txbuf *tb;
2350 int error;
2351
2352 ASSERT_SERIALIZED(ifp->if_serializer);
2353
2354 KKASSERT(tr->tr_index < IWL2100_TX_NDESC);
2355 tb = &tr->tr_buf[tr->tr_index];
2356
2357 ctx.nsegs = 1;
2358 ctx.segs = &seg;
2359 error = bus_dmamap_load_mbuf(sc->sc_mbuf_dtag, tb->tb_dmap, m,
2360 iwl_dma_buf_addr, &ctx, BUS_DMA_WAITOK);
2361 if (error || ctx.nsegs == 0) {
2362 if (!error) {
2363 bus_dmamap_unload(sc->sc_mbuf_dtag, tb->tb_dmap);
2364 error = EFBIG;
2365 if_printf(ifp, "too many segments?!\n");
2366 }
2367
2368 if_printf(ifp, "can't load RX mbuf\n");
2369 return error;
2370 }
2371 tb->tb_mbuf = sc->sc_cmd;
2372 tb->tb_flags |= IWL2100_TBF_CMDBUF;
2373
2374 d = &tr->tr_desc[tr->tr_index];
2375 d->d_paddr = seg.ds_addr;
2376 d->d_len = sizeof(struct iwl2100_cmd);
2377 d->d_nfrag = 1;
2378 d->d_flags = IWL2100_TXD_F_INTR | IWL2100_TXD_F_CMD;
2379
2380 KKASSERT(tr->tr_used < IWL2100_TX_NDESC);
2381 ++tr->tr_used;
2382 tr->tr_index = (tr->tr_index + 1) % IWL2100_TX_NDESC;
2383
2384 bus_dmamap_sync(tr->tr_dtag, tr->tr_dmap, BUS_DMASYNC_PREWRITE);
2385
2386 CSR_WRITE_4(sc, IWL2100_TXQ_WRITE_IDX, tr->tr_index);
2387
2388 if (sc->sc_flags & IWL2100_F_IN_INTR)
ed20d0e3 2389 panic("sleep in interrupt thread");
4fa322a1
SZ
2390
2391 sc->sc_flags |= IWL2100_F_WAITCMD;
ed3f6624 2392 error = zsleep(sc, ifp->if_serializer, 0, "iwlcmd", 2 * hz);
4fa322a1
SZ
2393 if (!error) {
2394 sc->sc_flags &= ~IWL2100_F_WAITCMD;
2395 if (sc->sc_flags & IWL2100_F_ERROR) {
2396 if_printf(ifp, "error happened when waiting "
2397 "command to be done\n");
2398 error = EIO;
2399 }
2400 }
2401 return error;
2402}
2403
2404static void
2405iwl2100_rxeof(struct iwl2100_softc *sc)
2406{
2407 struct iwl2100_rx_ring *rr = &sc->sc_rxring;
2408 struct ifnet *ifp = &sc->sc_ic.ic_if;
2409 int hwidx, i;
2410
2411 hwidx = CSR_READ_4(sc, IWL2100_RXQ_READ_IDX);
2412 CSR_READ_4(sc, IWL2100_RXQ_WRITE_IDX);
2413
2414 if (hwidx >= IWL2100_RX_NDESC) {
2415 if_printf(ifp, "invalid hardware RX index %d\n", hwidx);
2416 return;
2417 }
2418
2419 KKASSERT(rr->rr_index < IWL2100_RX_NDESC);
2420 i = (rr->rr_index + 1) % IWL2100_RX_NDESC;
2421 while (hwidx != i) {
2422 struct iwl2100_rx_status *st = &rr->rr_status[i];
2423 struct iwl2100_rxbuf *rb = &rr->rr_buf[i];
2424 int frame_type;
2425
2426 bus_dmamap_sync(rr->rr_st_dtag, rr->rr_st_dmap,
2427 BUS_DMASYNC_POSTREAD);
2428 frame_type = st->r_status & IWL2100_RXS_TYPE_MASK;
2429
2430 bus_dmamap_sync(sc->sc_mbuf_dtag, rb->rb_dmap,
2431 BUS_DMASYNC_POSTREAD);
2432 switch (frame_type) {
2433 case IWL2100_RXS_TYPE_CMD:
2434 iwl2100_rxeof_cmd(sc, i);
2435 break;
2436
2437 case IWL2100_RXS_TYPE_STATUS:
2438 iwl2100_rxeof_status(sc, i);
2439 break;
2440
2441 case IWL2100_RXS_TYPE_NOTE:
2442 iwl2100_rxeof_note(sc, i);
2443 break;
2444
2445 case IWL2100_RXS_TYPE_DATA:
2446 case IWL2100_RXS_TYPE_DATA1:
2447 iwl2100_rxeof_data(sc, i);
2448 break;
2449
2450 default:
2451 if_printf(ifp, "unknown frame type: %d\n", frame_type);
2452 iwl2100_rxdesc_setup(sc, i);
2453 break;
2454 }
2455 i = (i + 1) % IWL2100_RX_NDESC;
2456 }
2457 bus_dmamap_sync(rr->rr_st_dtag, rr->rr_st_dmap, BUS_DMASYNC_POSTREAD);
2458 bus_dmamap_sync(rr->rr_dtag, rr->rr_dmap, BUS_DMASYNC_POSTREAD);
2459
2460 if (i == 0)
2461 rr->rr_index = IWL2100_RX_NDESC - 1;
2462 else
2463 rr->rr_index = i - 1;
2464 CSR_WRITE_4(sc, IWL2100_RXQ_WRITE_IDX, rr->rr_index);
2465}
2466
2467static void
2468iwl2100_txeof(struct iwl2100_softc *sc)
2469{
2470 struct iwl2100_tx_ring *tr = &sc->sc_txring;
2471 struct ifnet *ifp = &sc->sc_ic.ic_if;
2472 int hwidx;
2473
2474 hwidx = CSR_READ_4(sc, IWL2100_TXQ_READ_IDX);
2475 CSR_READ_4(sc, IWL2100_TXQ_WRITE_IDX);
2476 if (hwidx >= IWL2100_TX_NDESC) {
2477 if_printf(ifp, "invalid hardware TX index %d\n", hwidx);
2478 return;
2479 }
2480
2481 KKASSERT(tr->tr_coll < IWL2100_TX_NDESC);
2482 while (tr->tr_used) {
2483 struct iwl2100_txbuf *tb;
2484
2485 if (tr->tr_coll == hwidx)
2486 break;
2487
2488 tb = &tr->tr_buf[tr->tr_coll];
2489 if (tb->tb_mbuf == NULL)
2490 goto next;
2491
2492 bus_dmamap_unload(sc->sc_mbuf_dtag, tb->tb_dmap);
2493 if (tb->tb_flags & IWL2100_TBF_CMDBUF) {
2494 tb->tb_flags &= ~IWL2100_TBF_CMDBUF;
2495 KKASSERT(tb->tb_mbuf == sc->sc_cmd);
2496 } else {
2497 m_freem(tb->tb_mbuf);
2498 }
2499 tb->tb_mbuf = NULL;
2500next:
2501 tr->tr_coll = (tr->tr_coll + 1) % IWL2100_TX_NDESC;
2502
2503 KKASSERT(tr->tr_used > 0);
2504 --tr->tr_used;
2505 }
2506
2507 if (tr->tr_used < IWL2100_TX_USED_MAX) {
2508 if (tr->tr_used == 0) {
2509 KKASSERT(tr->tr_coll == tr->tr_index);
2510 sc->sc_tx_timer = 0;
2511 }
2512
9ed293e0 2513 ifq_clr_oactive(&ifp->if_snd);
9db4b353 2514 if_devstart(ifp);
4fa322a1
SZ
2515 }
2516}
2517
2518static int
2519iwl2100_config(struct iwl2100_softc *sc, const uint8_t *bssid,
2520 const uint8_t *essid, uint8_t esslen, int ibss_chan)
2521{
2522 struct ieee80211com *ic = &sc->sc_ic;
2523 struct ifnet *ifp = &ic->ic_if;
2524 int error;
2525
2526 if (ic->ic_opmode == IEEE80211_M_MONITOR) {
2527 error = iwl2100_set_chan(sc, ic->ic_curchan);
2528 if (error) {
2529 if_printf(ifp, "can't set mon channel\n");
2530 return error;
2531 }
2532 }
2533
2534 IEEE80211_ADDR_COPY(ic->ic_myaddr, IF_LLADDR(ifp));
2535 error = iwl2100_set_addr(sc, ic->ic_myaddr);
2536 if (error) {
2537 if_printf(ifp, "can't set MAC address\n");
2538 return error;
2539 }
2540
2541 error = iwl2100_set_opmode(sc, ic->ic_opmode);
2542 if (error) {
2543 if_printf(ifp, "can't set opmode\n");
2544 return error;
2545 }
2546
2547 if (ibss_chan) {
2548 KKASSERT(ic->ic_opmode == IEEE80211_M_IBSS);
2549 error = iwl2100_set_chan(sc, ic->ic_curchan);
2550 if (error) {
2551 if_printf(ifp, "can't set ibss channel\n");
2552 return error;
2553 }
2554 }
2555
2556 error = iwl2100_set_80211(sc);
2557 if (error) {
2558 if_printf(ifp, "can't set 802.11 config\n");
2559 return error;
2560 }
2561
2562 error = iwl2100_set_basicrates(sc);
2563 if (error) {
2564 if_printf(ifp, "can't set basicrates\n");
2565 return error;
2566 }
2567
2568 error = iwl2100_set_txrates(sc);
2569 if (error) {
2570 if_printf(ifp, "can't set TX rates\n");
2571 return error;
2572 }
2573
2574 error = iwl2100_set_powersave(sc, ic->ic_flags & IEEE80211_F_PMGTON);
2575 if (error) {
2576 if_printf(ifp, "can't turn off powersave\n");
2577 return error;
2578 }
2579
2580 error = iwl2100_set_rtsthreshold(sc, ic->ic_rtsthreshold);
2581 if (error) {
2582 if_printf(ifp, "can't set RTS threshold\n");
2583 return error;
2584 }
2585
2586 error = iwl2100_set_bssid(sc, bssid);
2587 if (error) {
2588 if_printf(ifp, "can't set bssid\n");
2589 return error;
2590 }
2591
2592 error = iwl2100_set_essid(sc, essid, esslen);
2593 if (error) {
2594 if_printf(ifp, "can't set essid\n");
2595 return error;
2596 }
2597
2598 error = iwl2100_set_auth_ciphers(sc, ic->ic_bss->ni_authmode);
2599 if (error) {
2600 if_printf(ifp, "can't set authmode and ciphers\n");
2601 return error;
2602 }
2603
2604 if (ic->ic_flags & IEEE80211_F_PRIVACY) {
2605 ieee80211_keyix txkey = IEEE80211_KEYIX_NONE;
2606 int i;
2607
2608 for (i = 0; i < IEEE80211_WEP_NKID; ++i) {
2609 const struct ieee80211_key *k = &ic->ic_nw_keys[i];
2610
2611 if (k->wk_keyix == IEEE80211_KEYIX_NONE)
2612 continue;
2613
2614 error = iwl2100_set_wepkey(sc, k);
2615 if (error == E2BIG) {
2616 continue;
2617 } else if (error) {
2618 if_printf(ifp, "can't set wepkey\n");
2619 return error;
2620 }
2621 txkey = k->wk_keyix;
2622 }
2623
2624 if (txkey != IEEE80211_KEYIX_NONE) {
2625 /*
2626 * Found some valid WEP keys.
2627 *
2628 * If WEP TX key index from 802.11 layer is not
2629 * set, then use the first valid WEP key as TX
2630 * key.
2631 */
2632 if (ic->ic_def_txkey != IEEE80211_KEYIX_NONE)
2633 txkey = ic->ic_def_txkey;
2634
2635 error = iwl2100_set_weptxkey(sc, txkey);
2636 if (error) {
2637 if_printf(ifp, "can't set weptxkey\n");
2638 return error;
2639 }
2640 }
2641 }
2642
2643 error = iwl2100_set_privacy(sc, ic->ic_flags & IEEE80211_F_PRIVACY);
2644 if (error) {
2645 if_printf(ifp, "can't set privacy\n");
2646 return error;
2647 }
2648
2649 error = iwl2100_set_optie(sc, ic->ic_opt_ie, ic->ic_opt_ie_len);
2650 if (error) {
2651 if (error != E2BIG) {
2652 if_printf(ifp, "can't set opt ie\n");
2653 return error;
2654 }
2655 }
2656
2657 if (ic->ic_opmode == IEEE80211_M_IBSS) {
2658 error = iwl2100_set_bintval(sc, ic->ic_bss->ni_intval);
2659 if (error) {
2660 if_printf(ifp, "can't set bintval\n");
2661 return error;
2662 }
2663
2664 error = iwl2100_set_txpower(sc, 32 /* XXX */);
2665 if (error) {
2666 if_printf(ifp, "can't set txpwr\n");
2667 return error;
2668 }
2669 }
2670 return 0;
2671}
2672
2673static int
2674iwl2100_config_op(struct iwl2100_softc *sc, uint32_t op)
2675{
2676 struct iwl2100_cmd *cmd;
2677 int error;
2678
2679 KASSERT(op == IWL2100_CMD_CONF_DONE || op == IWL2100_CMD_CONF_START,
2680 ("unknown config_op %u", op));
2681
2682 if (sc->sc_flags & IWL2100_F_WAITCMD) {
2683 if_printf(&sc->sc_ic.ic_if, "there is command pending\n");
2684 return EEXIST;
2685 }
2686
2687 cmd = mtod(sc->sc_cmd, struct iwl2100_cmd *);
8075c3b8 2688 bzero(cmd, sizeof(*cmd));
4fa322a1
SZ
2689 cmd->c_cmd = op;
2690
2691 error = iwl2100_wait_cmd(sc);
2692 if (error) {
2693 if_printf(&sc->sc_ic.ic_if, "%s(%u) failed\n", __func__, op);
2694 return error;
2695 }
2696
2697 iwl2100_read_ord1(sc, IWL2100_ORD1_CONF_START); /* dummy read */
2698 return 0;
2699}
2700
2701static int
2702iwl2100_set_chan(struct iwl2100_softc *sc, const struct ieee80211_channel *c)
2703{
2704 struct ieee80211com *ic = &sc->sc_ic;
2705 struct iwl2100_cmd *cmd;
2706 u_int chan;
2707 int error;
2708
2709 KKASSERT(ic->ic_opmode != IEEE80211_M_STA);
2710
2711 chan = ieee80211_chan2ieee(ic, c);
2712 if (chan == IEEE80211_CHAN_ANY) {
2713 if_printf(&ic->ic_if, "invalid channel!\n");
2714 return EINVAL;
2715 }
2716
2717 if (sc->sc_flags & IWL2100_F_WAITCMD) {
2718 if_printf(&ic->ic_if, "there is command pending\n");
2719 return EEXIST;
2720 }
2721
2722 cmd = mtod(sc->sc_cmd, struct iwl2100_cmd *);
8075c3b8 2723 bzero(cmd, sizeof(*cmd));
4fa322a1
SZ
2724
2725 cmd->c_cmd = IWL2100_CMD_SET_CHAN;
2726 cmd->c_param_len = sizeof(cmd->c_param[0]);
2727 cmd->c_param[0] = chan;
2728
2729 error = iwl2100_wait_cmd(sc);
2730 if (error) {
2731 if_printf(&ic->ic_if, "%s failed\n", __func__);
2732 return error;
2733 }
2734 return 0;
2735}
2736
2737static int
2738iwl2100_set_scanopt(struct iwl2100_softc *sc, uint32_t chans, uint32_t flags)
2739{
2740 struct ieee80211com *ic = &sc->sc_ic;
2741 struct iwl2100_cmd *cmd;
2742 int error;
2743
2744 KKASSERT(ic->ic_opmode != IEEE80211_M_MONITOR);
2745
2746 if (sc->sc_flags & IWL2100_F_WAITCMD) {
2747 if_printf(&ic->ic_if, "there is command pending\n");
2748 return EEXIST;
2749 }
2750
2751 cmd = mtod(sc->sc_cmd, struct iwl2100_cmd *);
8075c3b8 2752 bzero(cmd, sizeof(*cmd));
4fa322a1
SZ
2753
2754 /*
2755 * NOTE:
2756 * 1) IWL2100_SCANOPT_NOASSOC is ignored by firmware, but same
2757 * function could be achieved by clearing bssid.
2758 * 2) Channel mask is ignored by firmware, if NIC is in STA opmode.
2759 *
2760 * We leave the correct configuration here just with the hope
2761 * that one day firmware could do better.
2762 */
2763 cmd->c_cmd = IWL2100_CMD_SET_SCANOPT;
2764 cmd->c_param_len = sizeof(cmd->c_param[0]) * 2;
2765 cmd->c_param[0] = flags | IWL2100_SCANOPT_MIXED;
2766 cmd->c_param[1] = chans;
2767
2768 error = iwl2100_wait_cmd(sc);
2769 if (error) {
2770 if_printf(&ic->ic_if, "%s failed\n", __func__);
2771 return error;
2772 }
2773 return 0;
2774}
2775
2776static int
2777iwl2100_set_scan(struct iwl2100_softc *sc)
2778{
2779 struct ieee80211com *ic = &sc->sc_ic;
2780 struct iwl2100_cmd *cmd;
2781 int error;
2782
2783 KKASSERT(ic->ic_opmode != IEEE80211_M_MONITOR);
2784
2785 if (sc->sc_flags & IWL2100_F_WAITCMD) {
2786 if_printf(&ic->ic_if, "there is command pending\n");
2787 return EEXIST;
2788 }
2789
2790 cmd = mtod(sc->sc_cmd, struct iwl2100_cmd *);
8075c3b8 2791 bzero(cmd, sizeof(*cmd));
4fa322a1
SZ
2792
2793 cmd->c_cmd = IWL2100_CMD_SCAN;
2794 cmd->c_param_len = sizeof(cmd->c_param[0]);
2795
2796 error = iwl2100_wait_cmd(sc);
2797 if (error) {
2798 if_printf(&ic->ic_if, "%s failed\n", __func__);
2799 return error;
2800 }
2801 return 0;
2802}
2803
2804static int
2805iwl2100_set_optie(struct iwl2100_softc *sc, void *optie, uint16_t optie_len)
2806{
2807 struct iwl2100_cmd *cmd;
2808 struct iwl2100_cmdparam_ie *ie;
2809 int error;
2810
2811 if (sc->sc_flags & IWL2100_F_WAITCMD) {
2812 if_printf(&sc->sc_ic.ic_if, "there is command pending\n");
2813 return EEXIST;
2814 }
2815
2816 if (optie_len > IWL2100_OPTIE_MAX) {
2817 if_printf(&sc->sc_ic.ic_if, "optie too long\n");
2818 return E2BIG;
2819 }
2820
2821 if (optie == NULL || optie_len == 0)
2822 return 0;
2823
2824 cmd = mtod(sc->sc_cmd, struct iwl2100_cmd *);
8075c3b8 2825 bzero(cmd, sizeof(*cmd));
4fa322a1
SZ
2826
2827 cmd->c_cmd = IWL2100_CMD_SET_IE;
2828 cmd->c_param_len = sizeof(*ie);
2829 ie = (struct iwl2100_cmdparam_ie *)cmd->c_param;
2830 ie->ie_optlen = optie_len;
2831 bcopy(optie, ie->ie_opt, optie_len);
2832
2833 error = iwl2100_wait_cmd(sc);
2834 if (error) {
2835 if_printf(&sc->sc_ic.ic_if, "%s failed\n", __func__);
2836 return error;
2837 }
2838 return 0;
2839}
2840
2841static int
2842iwl2100_set_bintval(struct iwl2100_softc *sc, uint16_t bintval)
2843{
2844 struct iwl2100_cmd *cmd;
2845 int error;
2846
2847 if (sc->sc_flags & IWL2100_F_WAITCMD) {
2848 if_printf(&sc->sc_ic.ic_if, "there is command pending\n");
2849 return EEXIST;
2850 }
2851
2852 cmd = mtod(sc->sc_cmd, struct iwl2100_cmd *);
8075c3b8 2853 bzero(cmd, sizeof(*cmd));
4fa322a1
SZ
2854
2855 cmd->c_cmd = IWL2100_CMD_SET_BINTVAL;
2856 cmd->c_param_len = sizeof(cmd->c_param[0]);
2857 cmd->c_param[0] = bintval;
2858
2859 error = iwl2100_wait_cmd(sc);
2860 if (error) {
2861 if_printf(&sc->sc_ic.ic_if, "%s failed\n", __func__);
2862 return error;
2863 }
2864 return 0;
2865}
2866
2867static int
2868iwl2100_set_txpower(struct iwl2100_softc *sc, uint16_t txpower)
2869{
2870 struct iwl2100_cmd *cmd;
2871 int error;
2872
2873 if (sc->sc_flags & IWL2100_F_WAITCMD) {
2874 if_printf(&sc->sc_ic.ic_if, "there is command pending\n");
2875 return EEXIST;
2876 }
2877
2878 cmd = mtod(sc->sc_cmd, struct iwl2100_cmd *);
8075c3b8 2879 bzero(cmd, sizeof(*cmd));
4fa322a1
SZ
2880
2881 cmd->c_cmd = IWL2100_CMD_SET_TXPOWER;
2882 cmd->c_param_len = sizeof(cmd->c_param[0]);
2883 cmd->c_param[0] = txpower;
2884
2885 error = iwl2100_wait_cmd(sc);
2886 if (error) {
2887 if_printf(&sc->sc_ic.ic_if, "%s failed\n", __func__);
2888 return error;
2889 }
2890 return 0;
2891}
2892
2893static void
2894iwl2100_rxeof_status(struct iwl2100_softc *sc, int i)
2895{
2896 struct ieee80211com *ic = &sc->sc_ic;
2897 struct ifnet *ifp = &ic->ic_if;
2898 struct iwl2100_rx_ring *rr = &sc->sc_rxring;
2899 struct iwl2100_rx_status *st = &rr->rr_status[i];
2900 struct iwl2100_rxbuf *rb = &rr->rr_buf[i];
2901 struct mbuf *m = rb->rb_mbuf;
2902 uint32_t status;
2903
2904 if (st->r_len != sizeof(status)) {
2905 if_printf(ifp, "invalid status frame len %u\n", st->r_len);
2906 goto back;
2907 }
2908
2909 if (ic->ic_opmode == IEEE80211_M_MONITOR)
2910 goto back;
2911
2912 if ((ic->ic_flags & IEEE80211_F_SCAN) == 0)
2913 sc->sc_flags &= ~IWL2100_F_SCANNING;
2914
2915 status = *mtod(m, uint32_t *);
2916 DPRINTF(sc, IWL2100_DBG_STATUS, "status 0x%08x\n", status);
2917
2918 switch (status) {
2919 case IWL2100_STATUS_SCANDONE:
2920 if (ic->ic_flags & IEEE80211_F_SCAN) {
2921 /*
2922 * To make sure that firmware has iterated all
2923 * of the channels, we wait for the second scan
2924 * done status change.
2925 */
2926 if (sc->sc_flags & IWL2100_F_SCANNING) {
2927 iwlmsg_send(&sc->sc_scanend_msg,
2928 &sc->sc_thread_port);
2929 } else {
2930 sc->sc_flags |= IWL2100_F_SCANNING;
2931 }
2932 }
2933 break;
2934
2935 case IWL2100_STATUS_RUNNING:
2936 iwl2100_restart_done(sc);
2937 if (ic->ic_state == IEEE80211_S_ASSOC) {
2938 KKASSERT(ic->ic_opmode == IEEE80211_M_STA);
2939 iwlmsg_send(&sc->sc_run_msg, &sc->sc_thread_port);
2940 } else if (ic->ic_state == IEEE80211_S_RUN) {
2941 if (ic->ic_opmode == IEEE80211_M_STA) {
2942 DPRINTF(sc, IWL2100_DBG_RESTART, "%s",
2943 "restart done\n");
2944 sc->sc_flags |= IWL2100_F_IFSTART;
9db4b353 2945 if_devstart(ifp);
4fa322a1
SZ
2946 } else {
2947 KKASSERT(ic->ic_opmode == IEEE80211_M_IBSS);
2948 callout_reset(&sc->sc_ibss, (100 * hz) / 1000,
2949 iwl2100_ibss_bssid, sc);
2950 }
2951 }
2952 break;
2953
2954 case IWL2100_STATUS_BMISS:
2955 if (ic->ic_opmode == IEEE80211_M_STA) {
2956 DPRINTF(sc, IWL2100_DBG_SCAN, "%s", "bmiss\n");
2957 iwlmsg_send(&sc->sc_bmiss_msg, &sc->sc_thread_port);
2958 }
2959 break;
2960
2961 case IWL2100_STATUS_SCANNING:
2962 if (ic->ic_opmode == IEEE80211_M_STA &&
2963 ic->ic_state == IEEE80211_S_RUN) {
2964 /* Firmware error happens */
2965 iwl2100_restart(sc);
2966 }
2967 break;
2968 }
2969back:
2970 iwl2100_rxdesc_setup(sc, i);
2971}
2972
2973static void
2974iwl2100_rxeof_note(struct iwl2100_softc *sc, int i)
2975{
2976 struct iwl2100_rx_ring *rr = &sc->sc_rxring;
2977 struct iwl2100_rx_status *st = &rr->rr_status[i];
2978 struct iwl2100_rxbuf *rb = &rr->rr_buf[i];
2979 struct mbuf *m = rb->rb_mbuf;
2980 struct ieee80211com *ic = &sc->sc_ic;
2981 struct iwl2100_note *note;
2982
2983 if (st->r_len < sizeof(*note)) {
2984 if_printf(&ic->ic_if, "invalid note frame len %u\n", st->r_len);
2985 goto back;
2986 }
2987
2988 if (ic->ic_opmode == IEEE80211_M_MONITOR)
2989 goto back;
2990
2991 note = mtod(m, struct iwl2100_note *);
2992 DPRINTF(sc, IWL2100_DBG_NOTE, "note subtype %u, size %u\n",
2993 note->nt_subtype, note->nt_size);
2994
2995 if (note->nt_subtype == 19 /* XXX */ &&
2996 ic->ic_state == IEEE80211_S_AUTH) {
2997 KKASSERT(ic->ic_opmode == IEEE80211_M_STA);
2998 iwlmsg_send(&sc->sc_assoc_msg, &sc->sc_thread_port);
2999 }
3000back:
3001 iwl2100_rxdesc_setup(sc, i);
3002}
3003
3004static void
3005iwl2100_rxeof_cmd(struct iwl2100_softc *sc, int i)
3006{
3007 struct iwl2100_rx_ring *rr = &sc->sc_rxring;
3008 struct iwl2100_rx_status *st = &rr->rr_status[i];
3009 struct iwl2100_rxbuf *rb = &rr->rr_buf[i];
3010 struct mbuf *m = rb->rb_mbuf;
3011 struct iwl2100_cmd *cmd;
3012
3013 if (st->r_len != sizeof(*cmd)) {
3014 if_printf(&sc->sc_ic.ic_if,
3015 "invalid cmd done frame len %u\n", st->r_len);
3016 goto back;
3017 }
3018
3019 cmd = mtod(m, struct iwl2100_cmd *);
e175c5b6
SZ
3020 DPRINTF(sc, IWL2100_DBG_CMD, "cmd %u\n", cmd->c_cmd);
3021 if (cmd->c_cmd == 0)
3022 sc->sc_flags |= IWL2100_F_ZERO_CMD;
4fa322a1
SZ
3023 wakeup(sc);
3024back:
3025 iwl2100_rxdesc_setup(sc, i);
3026}
3027
3028static void
3029iwl2100_rxeof_data(struct iwl2100_softc *sc, int i)
3030{
3031 struct ieee80211com *ic = &sc->sc_ic;
3032 struct ifnet *ifp = &ic->ic_if;
3033 struct iwl2100_rx_ring *rr = &sc->sc_rxring;
3034 struct iwl2100_rx_status *st = &rr->rr_status[i];
3035 struct iwl2100_rxbuf *rb = &rr->rr_buf[i];
3036 struct mbuf *m = rb->rb_mbuf;
3037 struct ieee80211_frame_min *wh;
3038 struct ieee80211_node *ni;
3039 int frame_len, rssi;
3040 const struct ieee80211_channel *c;
3041
3042 /*
3043 * Gather all necessary information from status ring _here_,
3044 * since the following iwl2100_newbuf() will clear them out.
3045 */
3046 rssi = st->r_rssi;
3047 frame_len = st->r_len;
3048
3049 if (iwl2100_newbuf(sc, i, 0)) {
d40991ef 3050 IFNET_STAT_INC(ifp, ierrors, 1);
4fa322a1
SZ
3051 return;
3052 }
3053
3054 c = ic->ic_curchan;
3055
3056 m->m_pkthdr.rcvif = ifp;
3057 m->m_len = m->m_pkthdr.len = frame_len;
3058
3059 wh = mtod(m, struct ieee80211_frame_min *);
3060 ni = ieee80211_find_rxnode(ic, wh);
3061
3062 /*
3063 * RX radio tap
3064 */
3065 if (sc->sc_drvbpf != NULL) {
085ff963 3066 if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED)
4fa322a1
SZ
3067 sc->sc_rx_th.wr_flags = IEEE80211_RADIOTAP_F_WEP;
3068 else
3069 sc->sc_rx_th.wr_flags = 0;
3070
3071 sc->sc_rx_th.wr_antsignal = rssi + IWL2100_NOISE_FLOOR;
3072 sc->sc_rx_th.wr_antnoise = IWL2100_NOISE_FLOOR;
3073
3074 bpf_ptap(sc->sc_drvbpf, m, &sc->sc_rx_th, sc->sc_rx_th_len);
3075 }
3076
3077 ieee80211_input(ic, m, ni, rssi, 0);
3078 ieee80211_free_node(ni);
3079
3080 if (c != ic->ic_curchan) /* Happen during scanning */
3081 iwl2100_chan_change(sc, ic->ic_curchan);
3082}
3083
3084static void
3085iwl2100_scanend_dispatch(struct netmsg *nmsg)
3086{
3087 struct iwlmsg *msg = (struct iwlmsg *)nmsg;
3088 struct iwl2100_softc *sc = msg->iwlm_softc;
3089 struct ieee80211com *ic = &sc->sc_ic;
3090 struct ifnet *ifp = &ic->ic_if;
3091
3092 ASSERT_SERIALIZED(ifp->if_serializer);
3093
e175c5b6
SZ
3094 if (sc->sc_flags & IWL2100_F_DETACH)
3095 goto reply;
3096
4fa322a1
SZ
3097 if (ifp->if_flags & IFF_RUNNING) {
3098 ieee80211_end_scan(ic);
3099 sc->sc_flags &= ~IWL2100_F_SCANNING;
3100 }
e175c5b6 3101reply:
4fa322a1
SZ
3102 lwkt_replymsg(&nmsg->nm_lmsg, 0);
3103}
3104
3105static int
3106iwl2100_hw_init(struct iwl2100_softc *sc, const uint8_t *bssid,
3107 const uint8_t *essid, uint8_t esslen, uint32_t flags)
3108{
3109 struct ieee80211com *ic = &sc->sc_ic;
3110 struct ifnet *ifp = &ic->ic_if;
3111 uint32_t db_addr;
3112 int error;
3113
3114 ASSERT_SERIALIZED(ifp->if_serializer);
3115 KKASSERT(curthread == &sc->sc_thread);
3116
3117 iwl2100_hw_stop(sc);
3118
3119 error = iwl2100_alloc_firmware(sc, ic->ic_opmode);
3120 if (error) {
3121 if_printf(ifp, "can't allocate firmware\n");
3122 goto back;
3123 }
3124
3125 error = iwl2100_load_firmware(sc, ic->ic_opmode);
3126 if (error) {
3127 if_printf(ifp, "can't load firmware\n");
3128 goto back;
3129 }
3130
3131 error = iwl2100_alloc_cmd(sc);
3132 if (error) {
3133 if_printf(ifp, "can't allocate cmd\n");
3134 goto back;
3135 }
3136
3137 error = iwl2100_init_tx_ring(sc);
3138 if (error) {
3139 if_printf(ifp, "can't init TX ring\n");
3140 goto back;
3141 }
3142
3143 error = iwl2100_init_rx_ring(sc);
3144 if (error) {
3145 if_printf(ifp, "can't init RX ring\n");
3146 goto back;
3147 }
3148
3149 error = iwl2100_init_firmware(sc);
3150 if (error) {
3151 if_printf(ifp, "can't initialize firmware\n");
3152 goto back;
3153 }
3154
3155 sc->sc_ord1 = CSR_READ_4(sc, IWL2100_ORD1_ADDR);
3156 sc->sc_ord2 = CSR_READ_4(sc, IWL2100_ORD2_ADDR);
3157
3158 db_addr = iwl2100_read_ord1(sc, IWL2100_ORD1_DBADDR);
3159 if ((IND_READ_4(sc, db_addr + 0x20) >> 24) & 0x1)
3160 sc->sc_caps &= ~IWL2100_C_RFKILL;
3161 else
3162 sc->sc_caps |= IWL2100_C_RFKILL;
3163
3164 /* Unlock firmware */
3165 iwl2100_write_ord1(sc, IWL2100_ORD1_FWLOCK, 0);
3166
3167 if (iwl2100_rfkilled(sc)) {
3168 error = ENXIO;
3169 goto back;
3170 }
3171
3172 /* Let interrupt handler run */
3173 sc->sc_flags |= IWL2100_F_INITED;
3174
3175 /* Enable interrupts */
3176 CSR_WRITE_4(sc, IWL2100_INTR_MASK, IWL2100_INTRS);
3177
3178 error = iwl2100_config(sc, bssid, essid, esslen,
3179 flags & IWL2100_INIT_F_IBSSCHAN);
3180 if (error)
3181 goto back;
3182
3183 if (flags & IWL2100_INIT_F_ENABLE) {
3184 error = iwl2100_config_done(sc);
3185 if (error) {
3186 if_printf(ifp, "can't complete config\n");
3187 goto back;
3188 }
3189 }
3190
9ed293e0 3191 ifq_clr_oactive(&ifp->if_snd);
4fa322a1
SZ
3192 ifp->if_flags |= IFF_RUNNING;
3193back:
3194 if (error)
3195 iwl2100_stop(sc);
3196 return error;
3197}
3198
3199static int
3200iwl2100_start_scan(struct iwl2100_softc *sc, uint32_t chans, uint32_t flags)
3201{
3202 int error;
3203
3204 /*
3205 * XXX
3206 * Firmware always starts scanning once config is done
3207 */
3208 error = iwl2100_set_scanopt(sc, chans, flags);
3209 if (error) {
3210 if_printf(&sc->sc_ic.ic_if, "can't set scan opt\n");
3211 return error;
3212 }
3213
3214 error = iwl2100_set_scan(sc);
3215 if (error) {
3216 if_printf(&sc->sc_ic.ic_if, "can't set bcast scanning\n");
3217 return error;
3218 }
3219 return 0;
3220}
3221
3222static int
3223iwl2100_scan(struct iwl2100_softc *sc)
3224{
3225 struct ieee80211com *ic = &sc->sc_ic;
3226 uint32_t chans, flags;
3227 int error;
3228
3229 KKASSERT(ic->ic_opmode != IEEE80211_M_MONITOR);
3230
3231 error = iwl2100_hw_init(sc, NULL,
3232 ic->ic_des_essid, ic->ic_des_esslen, IWL2100_INIT_F_ENABLE);
3233 if (error)
3234 return error;
3235
3236 if (ic->ic_opmode == IEEE80211_M_STA) {
3237 chans = sc->sc_bss_chans;
3238 flags = IWL2100_SCANOPT_NOASSOC;
3239 } else {
3240 /*
3241 * Normally # of IBSS channels is less than BSS's
3242 * but it seems IBSS mode works on all BSS channels
3243 */
3244#if 0
3245 chans = sc->sc_ibss_chans;
3246#else
3247 chans = sc->sc_bss_chans;
3248#endif
3249 /*
3250 * Don't set NOASSOC scan option, it seems that
3251 * firmware will disable itself after scanning
3252 * if this flag is set. After all, we are in
3253 * IBSS mode, which does not have concept of
3254 * association.
3255 */
3256 flags = 0;
3257 }
3258
3259 /* See NOTE in iwl2100_set_scanopt() */
3260 error = iwl2100_start_scan(sc, chans, flags);
3261 if (error)
3262 return error;
3263 return 0;
3264}
3265
3266static int
3267iwl2100_auth(struct iwl2100_softc *sc)
3268{
3269 struct ieee80211com *ic = &sc->sc_ic;
3270 struct ieee80211_node *ni = ic->ic_bss;
3271 u_int chan;
3272 int error;
3273
3274 KKASSERT(ic->ic_opmode == IEEE80211_M_STA);
3275
3276 chan = ieee80211_chan2ieee(ic, ic->ic_curchan);
3277 if (chan == IEEE80211_CHAN_ANY) {
3278 if_printf(&ic->ic_if, "invalid curchan\n");
3279 return EINVAL;
3280 }
3281
3282 error = iwl2100_hw_init(sc, ni->ni_bssid,
3283 ni->ni_essid, ni->ni_esslen, IWL2100_INIT_F_ENABLE);
3284 if (error)
3285 return error;
3286
3287 /* See NOTE in iwl2100_set_scanopt() */
3288 error = iwl2100_start_scan(sc, 1 << (chan - 1), 0);
3289 if (error)
3290 return error;
3291 return 0;
3292}
3293
3294static int
3295iwl2100_ibss(struct iwl2100_softc *sc)
3296{
3297 struct ieee80211com *ic = &sc->sc_ic;
3298 struct ieee80211_node *ni = ic->ic_bss;
3299
3300 return iwl2100_hw_init(sc, ni->ni_bssid,
3301 ni->ni_essid, ni->ni_esslen,
3302 IWL2100_INIT_F_ENABLE | IWL2100_INIT_F_IBSSCHAN);
3303}
3304
3305static int
3306iwl2100_encap(struct iwl2100_softc *sc, struct mbuf *m)
3307{
3308 struct iwl2100_tx_ring *tr = &sc->sc_txring;
3309 struct iwl2100_tx_hdr *th;
3310 struct ieee80211_frame *wh;
3311 struct iwl_dmamap_ctx ctx;
3312 bus_dma_segment_t segs[IWL2100_NSEG_MAX];
3313 uint8_t src[IEEE80211_ADDR_LEN], dst[IEEE80211_ADDR_LEN];
3314 bus_dmamap_t dmap;
3315 int maxsegs, i, first_idx, last_idx, error, host_enc;
3316
3317 /*
3318 * Save necessary information and strip 802.11 header
3319 */
3320 wh = mtod(m, struct ieee80211_frame *);
3321 IEEE80211_ADDR_COPY(src, wh->i_addr2);
3322 if (sc->sc_ic.ic_opmode == IEEE80211_M_STA)
3323 IEEE80211_ADDR_COPY(dst, wh->i_addr3);
3324 else
3325 IEEE80211_ADDR_COPY(dst, wh->i_addr1);
085ff963 3326 if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED)
4fa322a1
SZ
3327 host_enc = 1;
3328 else
3329 host_enc = 0;
3330 m_adj(m, sizeof(*wh));
3331
3332 /*
3333 * Prepend and setup hardware TX header
3334 */
3335 M_PREPEND(m, sizeof(*th), MB_DONTWAIT);
3336 if (m == NULL) {
3337 if_printf(&sc->sc_ic.ic_if, "prepend TX header failed\n");
3338 return ENOBUFS;
3339 }
3340 th = mtod(m, struct iwl2100_tx_hdr *);
3341
3342 bzero(th, sizeof(*th));
3343 th->th_cmd = IWL2100_CMD_TX_DATA;
3344 th->th_host_enc = host_enc;
3345 IEEE80211_ADDR_COPY(th->th_src, src);
3346 IEEE80211_ADDR_COPY(th->th_dst, dst);
3347
3348 /*
3349 * Load mbuf into DMA map
3350 */
3351 maxsegs = IWL2100_TX_USED_MAX - tr->tr_used;
3352 if (maxsegs > IWL2100_NSEG_MAX)
3353 maxsegs = IWL2100_NSEG_MAX;
3354
3355 KKASSERT(tr->tr_index < IWL2100_TX_NDESC);
3356 first_idx = tr->tr_index;
3357 dmap = tr->tr_buf[first_idx].tb_dmap;
3358
3359 ctx.nsegs = maxsegs;
3360 ctx.segs = segs;
3361 error = bus_dmamap_load_mbuf(sc->sc_mbuf_dtag, dmap, m,
3362 iwl_dma_buf_addr, &ctx, BUS_DMA_NOWAIT);
3363 if (!error && ctx.nsegs == 0) {
3364 bus_dmamap_unload(sc->sc_mbuf_dtag, dmap);
3365 error = EFBIG;
3366 }
3367 if (error && error != EFBIG) {
3368 if_printf(&sc->sc_ic.ic_if, "can't load TX mbuf, error %d\n",
3369 error);
3370 goto back;
3371 }
3372 if (error) { /* error == EFBIG */
3373 struct mbuf *m_new;
3374
3375 m_new = m_defrag(m, MB_DONTWAIT);
3376 if (m_new == NULL) {
3377 if_printf(&sc->sc_ic.ic_if, "can't defrag TX mbuf\n");
3378 error = ENOBUFS;
3379 goto back;
3380 } else {
3381 m = m_new;
3382 }
3383
3384 ctx.nsegs = maxsegs;
3385 ctx.segs = segs;
3386 error = bus_dmamap_load_mbuf(sc->sc_mbuf_dtag, dmap, m,
3387 iwl_dma_buf_addr, &ctx,
3388 BUS_DMA_NOWAIT);
3389 if (error || ctx.nsegs == 0) {
3390 if (ctx.nsegs == 0) {
3391 bus_dmamap_unload(sc->sc_mbuf_dtag, dmap);
3392 error = EFBIG;
3393 }
3394 if_printf(&sc->sc_ic.ic_if,
3395 "can't load defraged TX mbuf\n");
3396 goto back;
3397 }
3398 }
3399 bus_dmamap_sync(sc->sc_mbuf_dtag, dmap, BUS_DMASYNC_PREWRITE);
3400
3401 /*
3402 * Fill TX desc ring
3403 */
3404 last_idx = -1;
3405 for (i = 0; i < ctx.nsegs; ++i) {
3406 struct iwl2100_desc *d = &tr->tr_desc[tr->tr_index];
3407
3408 d->d_paddr = segs[i].ds_addr;
3409 d->d_len = segs[i].ds_len;
3410 if (i != 0)
3411 d->d_nfrag = 0;
3412 else
3413 d->d_nfrag = ctx.nsegs;
3414
3415 if (i == ctx.nsegs - 1) {
3416 d->d_flags = IWL2100_TXD_F_INTR;
3417 last_idx = tr->tr_index;
3418 } else {
3419 d->d_flags = IWL2100_TXD_F_NOTLAST;
3420 }
3421
3422 tr->tr_index = (tr->tr_index + 1) % IWL2100_TX_NDESC;
3423 }
3424 KKASSERT(last_idx >= 0);
3425
3426 tr->tr_buf[first_idx].tb_dmap = tr->tr_buf[last_idx].tb_dmap;
3427 tr->tr_buf[last_idx].tb_dmap = dmap;
3428 tr->tr_buf[last_idx].tb_mbuf = m;
3429
3430 tr->tr_used += ctx.nsegs;
3431 KKASSERT(tr->tr_used <= IWL2100_TX_USED_MAX);
3432
3433 error = 0;
3434back:
3435 if (error)
3436 m_freem(m);
3437 return error;
3438}
3439
3440static void
3441iwl2100_restart_dispatch(struct netmsg *nmsg)
3442{
3443 struct iwlmsg *msg = (struct iwlmsg *)nmsg;
3444 struct iwl2100_softc *sc = msg->iwlm_softc;
3445 struct ieee80211com *ic = &sc->sc_ic;
3446 struct ifnet *ifp = &ic->ic_if;
3447 int error = 0;
3448
3449 ASSERT_SERIALIZED(ifp->if_serializer);
3450
e175c5b6
SZ
3451 if (sc->sc_flags & IWL2100_F_DETACH)
3452 goto reply;
3453
4fa322a1
SZ
3454 if ((ifp->if_flags & IFF_RUNNING) == 0)
3455 goto reply;
3456
3457 if (msg->iwlm_arg != sc->sc_state_age) {
3458 /*
3459 * Restarting was triggered in old 802.11 state
3460 * Don't do anything, this is a staled restarting.
3461 */
3462 goto reply;
3463 }
3464
3465 if (ic->ic_state != IEEE80211_S_RUN) {
3466 if_printf(ifp, "restart happened when not in RUN state\n");
3467 goto reply;
3468 }
3469
3470 /*
3471 * iwl2100_auth() may release slizer, so stop all
3472 * callouts to prevent them from misfiring.
3473 */
3474 callout_stop(&sc->sc_restart_bmiss);
3475 callout_stop(&sc->sc_ibss);
3476
3477 if (ic->ic_opmode == IEEE80211_M_STA) {
3478 error = iwl2100_auth(sc);
3479 if (error)
3480 goto reply;
3481
3482 /*
3483 * Start software beacon missing to handle missing
3484 * firmware bmiss status change when we restarting
3485 */
3486 callout_reset(&sc->sc_restart_bmiss, IEEE80211_TU_TO_TICKS(
3487 2 * ic->ic_bmissthreshold * ic->ic_bss->ni_intval),
3488 iwl2100_restart_bmiss, sc);
3489 } else if (ic->ic_opmode == IEEE80211_M_IBSS) {
3490 error = iwl2100_ibss(sc);
3491 if (error)
3492 goto reply;
3493 }
3494
3495 /* Turn on restarting flag before reply this message */
3496 sc->sc_flags |= IWL2100_F_RESTARTING;
3497reply:
3498 lwkt_replymsg(&nmsg->nm_lmsg, error);
3499}
3500
3501static void
3502iwl2100_restart(struct iwl2100_softc *sc)
3503{
e175c5b6 3504 if ((sc->sc_flags & (IWL2100_F_RESTARTING | IWL2100_F_DETACH)) == 0) {
4fa322a1
SZ
3505 struct iwlmsg *msg = &sc->sc_restart_msg;
3506 struct lwkt_msg *lmsg = &msg->iwlm_nmsg.nm_lmsg;
3507
3508 DPRINTF(sc, IWL2100_DBG_RESTART, "%s", "restart\n");
3509 if (lmsg->ms_flags & MSGF_DONE) {
3510 sc->sc_flags &= ~IWL2100_F_IFSTART;
3511 msg->iwlm_arg = sc->sc_state_age;
3512 lwkt_sendmsg(&sc->sc_thread_port, lmsg);
3513 }
3514 }
3515}
3516
3517static void
3518iwl2100_bmiss_dispatch(struct netmsg *nmsg)
3519{
3520 struct iwlmsg *msg = (struct iwlmsg *)nmsg;
3521 struct iwl2100_softc *sc = msg->iwlm_softc;
3522 struct ieee80211com *ic = &sc->sc_ic;
3523 struct ifnet *ifp = &ic->ic_if;
3524
3525 ASSERT_SERIALIZED(ifp->if_serializer);
3526
e175c5b6
SZ
3527 if (sc->sc_flags & IWL2100_F_DETACH)
3528 goto reply;
3529
4fa322a1
SZ
3530 if (ifp->if_flags & IFF_RUNNING) {
3531 /*
3532 * Fake a ic_bmiss_count to make sure that
3533 * ieee80211_beacon_miss() will do its job
3534 */
3535 ic->ic_bmiss_count = ic->ic_bmiss_max;
3536 ieee80211_beacon_miss(ic);
3537 }
e175c5b6 3538reply:
4fa322a1
SZ
3539 lwkt_replymsg(&nmsg->nm_lmsg, 0);
3540}
3541
3542static void
3543iwl2100_restart_bmiss(void *xsc)
3544{
3545 struct iwl2100_softc *sc = xsc;
3546 struct ifnet *ifp = &sc->sc_ic.ic_if;
3547
3548 lwkt_serialize_enter(ifp->if_serializer);
3549
e175c5b6
SZ
3550 if (sc->sc_flags & IWL2100_F_DETACH)
3551 goto back;
3552
4fa322a1
SZ
3553 if ((ifp->if_flags & IFF_RUNNING) == 0)
3554 goto back;
3555
3556 if (sc->sc_flags & IWL2100_F_RESTARTING) {
3557 DPRINTF(sc, IWL2100_DBG_SCAN | IWL2100_DBG_RESTART, "%s",
3558 "restart bmiss\n");
3559 iwlmsg_send(&sc->sc_bmiss_msg, &sc->sc_thread_port);
3560 }
3561back:
3562 lwkt_serialize_exit(ifp->if_serializer);
3563}
3564
3565static void
3566iwl2100_ibss_bssid(void *xsc)
3567{
3568 struct iwl2100_softc *sc = xsc;
3569 struct ieee80211com *ic = &sc->sc_ic;
3570 struct ifnet *ifp = &ic->ic_if;
1e290df3 3571 char ethstr[ETHER_ADDRSTRLEN + 1];
4fa322a1
SZ
3572
3573 lwkt_serialize_enter(ifp->if_serializer);
3574
e175c5b6
SZ
3575 if (sc->sc_flags & IWL2100_F_DETACH)
3576 goto back;
3577
4fa322a1
SZ
3578 if ((ifp->if_flags & IFF_RUNNING) == 0)
3579 goto back;
3580
3581 if (ic->ic_state == IEEE80211_S_RUN &&
3582 ic->ic_opmode == IEEE80211_M_IBSS) {
3583 uint8_t bssid[IEEE80211_ADDR_LEN];
3584 int len;
3585
3586 len = iwl2100_read_ord2(sc, IWL2100_ORD2_BSSID,
3587 bssid, sizeof(bssid));
3588 if (len < (int)sizeof(bssid)) {
3589 if_printf(ifp, "can't get IBSS bssid\n");
3590 } else {
1e290df3
AHJ
3591 DPRINTF(sc, IWL2100_DBG_IBSS, "IBSS bssid: %s\n",
3592 kether_ntoa(bssid, ethstr));
4fa322a1
SZ
3593 IEEE80211_ADDR_COPY(ic->ic_bss->ni_bssid, bssid);
3594
3595 sc->sc_flags |= IWL2100_F_IFSTART;
9db4b353 3596 if_devstart(ifp);
4fa322a1
SZ
3597 }
3598 }
3599back:
3600 lwkt_serialize_exit(ifp->if_serializer);
3601}
3602
3603static void
e175c5b6 3604iwl2100_reinit(struct iwl2100_softc *sc)
4fa322a1
SZ
3605{
3606 struct ifnet *ifp = &sc->sc_ic.ic_if;
4fa322a1 3607
e175c5b6
SZ
3608 callout_stop(&sc->sc_restart_bmiss);
3609 callout_stop(&sc->sc_ibss);
4fa322a1
SZ
3610
3611 ifp->if_flags &= ~IFF_RUNNING;
3612 ifp->if_timer = 0;
3613
3614 sc->sc_flags &= ~IWL2100_F_INITED;
3615 sc->sc_tx_timer = 0;
3616
4fa322a1
SZ
3617 /* Mark error happened, and wake up the pending command */
3618 sc->sc_flags |= IWL2100_F_ERROR;
3619 wakeup(sc);
3620
e175c5b6
SZ
3621 if ((sc->sc_flags & IWL2100_F_DETACH) == 0) {
3622 /*
3623 * Schedule complete initialization,
3624 * i.e. blow away current state
3625 */
3626 iwlmsg_send(&sc->sc_reinit_msg, &sc->sc_thread_port);
3627 }
4fa322a1
SZ
3628}
3629
3630static void
3631iwl2100_reinit_dispatch(struct netmsg *nmsg)
3632{
3633 struct iwlmsg *msg = (struct iwlmsg *)nmsg;
3634 struct iwl2100_softc *sc = msg->iwlm_softc;
e175c5b6 3635 struct ifnet *ifp = &sc->sc_ic.ic_if;
4fa322a1 3636
e175c5b6 3637 ASSERT_SERIALIZED(ifp->if_serializer);
4fa322a1
SZ
3638
3639 /*
3640 * NOTE: Reply ASAP, so reinit msg could be used if error intr
3641 * happened again during following iwl2100_init()
3642 */
3643 lwkt_replymsg(&nmsg->nm_lmsg, 0);
e175c5b6
SZ
3644
3645 if (sc->sc_flags & IWL2100_F_DETACH)
3646 return;
3647
3648 if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == IFF_UP)
3649 iwl2100_init(sc);
3650}
3651
3652static void
3653iwl2100_reinit_callout(void *xsc)
3654{
3655 struct iwl2100_softc *sc = xsc;
3656 struct ifnet *ifp = &sc->sc_ic.ic_if;
3657
3658 lwkt_serialize_enter(ifp->if_serializer);
3659 if ((sc->sc_flags & IWL2100_F_DETACH) == 0)
3660 iwl2100_reinit(sc);
3661 lwkt_serialize_exit(ifp->if_serializer);
4fa322a1
SZ
3662}
3663
3664static void
3665iwl2100_chan_change(struct iwl2100_softc *sc, const struct ieee80211_channel *c)
3666{
3667 sc->sc_tx_th.wt_chan_freq = sc->sc_rx_th.wr_chan_freq =
3668 htole16(c->ic_freq);
3669}
e175c5b6
SZ
3670
3671static void
3672iwl2100_stop_callouts(struct iwl2100_softc *sc)
3673{
3674 callout_stop(&sc->sc_restart_bmiss);
3675 callout_stop(&sc->sc_ibss);
3676 callout_stop(&sc->sc_reinit);
3677}