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