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